let*_*ock 14 r vector data-partitioning
我有一个矢量,例如c(1, 3, 4, 5, 9, 10, 17, 29, 30),我想将"相邻"元素组合在一起,形成一个规则的连续序列,在一个参差不齐的矢量中导致:
L1:1
L2:3,4,5
L3:9,10
L4:17
L5:29,30
朴素代码(前C程序员):
partition.neighbors <- function(v)
{
result <<- list() #jagged array
currentList <<- v[1] #current series
for(i in 2:length(v))
{
if(v[i] - v [i-1] == 1)
{
currentList <<- c(currentList, v[i])
}
else
{
result <<- c(result, list(currentList))
currentList <<- v[i] #next series
}
}
return(result)
}
Run Code Online (Sandbox Code Playgroud)
现在我明白了
a)R不是C(尽管有大括号)
b)全局变量是纯粹的邪恶
c)这是一种实现结果的非常低效的方法
,欢迎任何更好的解决方案.
Jos*_*ich 16
大量使用一些R语言:
> split(v, cumsum(c(1, diff(v) != 1)))
$`1`
[1] 1
$`2`
[1] 3 4 5
$`3`
[1] 9 10
$`4`
[1] 17
$`5`
[1] 29 30
Run Code Online (Sandbox Code Playgroud)
Aar*_*ica 11
daroczig写道"你可以根据diff" 编写很多更整洁的代码"......
这是一种方式:
split(v, cumsum(diff(c(-Inf, v)) != 1))
Run Code Online (Sandbox Code Playgroud)
编辑(添加时间):
汤米发现通过小心类型可以更快; 它变得更快的原因split是整数更快,实际上更快的因素.
这是约书亚的解决方案; 来自cumsum数字的结果是因为它是c'd with 1,所以它是最慢的.
system.time({
a <- cumsum(c(1, diff(v) != 1))
split(v, a)
})
# user system elapsed
# 1.839 0.004 1.848
Run Code Online (Sandbox Code Playgroud)
只是c与荷兰国际集团1L这样的结果是一个整数,其加速增色不少.
system.time({
a <- cumsum(c(1L, diff(v) != 1))
split(v, a)
})
# user system elapsed
# 0.744 0.000 0.746
Run Code Online (Sandbox Code Playgroud)
这是汤米的解决方案,供参考; 它也分裂整数.
> system.time({
a <- cumsum(c(TRUE, diff(v) != 1L))
split(v, a)
})
# user system elapsed
# 0.742 0.000 0.746
Run Code Online (Sandbox Code Playgroud)
这是我原来的解决方案; 它也是在整数上分裂.
system.time({
a <- cumsum(diff(c(-Inf, v)) != 1)
split(v, a)
})
# user system elapsed
# 0.750 0.000 0.754
Run Code Online (Sandbox Code Playgroud)
这是Joshua的,结果在之前转换为整数split.
system.time({
a <- cumsum(c(1, diff(v) != 1))
a <- as.integer(a)
split(v, a)
})
# user system elapsed
# 0.736 0.002 0.740
Run Code Online (Sandbox Code Playgroud)
split整数向量上的所有版本大致相同; 如果整数向量已经是一个因子,它可能会更快,因为从整数到因子的转换实际上需要大约一半的时间.在这里,我直接将它变成一个因素; 一般不推荐这样做,因为它取决于因子类的结构.这里只是为了比较目的.
system.time({
a <- cumsum(c(1L, diff(v) != 1))
a <- structure(a, class = "factor", levels = 1L:a[length(a)])
split(v,a)
})
# user system elapsed
# 0.356 0.000 0.357
Run Code Online (Sandbox Code Playgroud)
约书亚和亚伦当场了.但是,通过仔细使用正确的类型,整数和逻辑,它们的代码仍然可以快两倍以上:
split(v, cumsum(c(TRUE, diff(v) != 1L)))
v <- rep(c(1:5, 19), len = 1e6) # Huge vector...
system.time( split(v, cumsum(c(1, diff(v) != 1))) ) # Joshua's code
# user system elapsed
# 2.64 0.00 2.64
system.time( split(v, cumsum(c(TRUE, diff(v) != 1L))) ) # Modified code
# user system elapsed
# 1.09 0.00 1.12
Run Code Online (Sandbox Code Playgroud)
您可以轻松定义切点:
which(diff(v) != 1)
Run Code Online (Sandbox Code Playgroud)
基于该尝试:
v <- c(1,3,4,5,9,10,17,29,30)
cutpoints <- c(0, which(diff(v) != 1), length(v))
ragged.vector <- vector("list", length(cutpoints)-1)
for (i in 2:length(cutpoints)) ragged.vector[[i-1]] <- v[(cutpoints[i-1]+1):cutpoints[i]]
Run Code Online (Sandbox Code Playgroud)
结果是:
> ragged.vector
[[1]]
[1] 1
[[2]]
[1] 3 4 5
[[3]]
[1] 9 10
[[4]]
[1] 17
[[5]]
[1] 29 30
Run Code Online (Sandbox Code Playgroud)
这个算法不是一个很好的算法,但你可以根据它编写很多更简洁的代码diff:)祝你好运!