我必须在r中把一个向量分成n个相等大小的块,我找不到任何基函数来做这个。谷歌也没帮上什么忙。这是我目前想到的;
x <- 1:10
n <- 3
chunk <- function(x,n) split(x, factor(sort(rank(x)%%n)))
chunk(x,n)
$`0`
[1] 1 2 3
$`1`
[1] 4 5 6 7
$`2`
[1] 8 9 10
我必须在r中把一个向量分成n个相等大小的块,我找不到任何基函数来做这个。谷歌也没帮上什么忙。这是我目前想到的;
x <- 1:10
n <- 3
chunk <- function(x,n) split(x, factor(sort(rank(x)%%n)))
chunk(x,n)
$`0`
[1] 1 2 3
$`1`
[1] 4 5 6 7
$`2`
[1] 8 9 10
当前回答
这将以不同的方式划分它,但我认为这仍然是一个相当不错的列表结构:
chunk.2 <- function(x, n, force.number.of.groups = TRUE, len = length(x), groups = trunc(len/n), overflow = len%%n) {
if(force.number.of.groups) {
f1 <- as.character(sort(rep(1:n, groups)))
f <- as.character(c(f1, rep(n, overflow)))
} else {
f1 <- as.character(sort(rep(1:groups, n)))
f <- as.character(c(f1, rep("overflow", overflow)))
}
g <- split(x, f)
if(force.number.of.groups) {
g.names <- names(g)
g.names.ordered <- as.character(sort(as.numeric(g.names)))
} else {
g.names <- names(g[-length(g)])
g.names.ordered <- as.character(sort(as.numeric(g.names)))
g.names.ordered <- c(g.names.ordered, "overflow")
}
return(g[g.names.ordered])
}
这将给你以下,取决于你想要它的格式:
> x <- 1:10; n <- 3
> chunk.2(x, n, force.number.of.groups = FALSE)
$`1`
[1] 1 2 3
$`2`
[1] 4 5 6
$`3`
[1] 7 8 9
$overflow
[1] 10
> chunk.2(x, n, force.number.of.groups = TRUE)
$`1`
[1] 1 2 3
$`2`
[1] 4 5 6
$`3`
[1] 7 8 9 10
使用这些设置运行几个计时:
set.seed(42)
x <- rnorm(1:1e7)
n <- 3
然后我们得到以下结果:
> system.time(chunk(x, n)) # your function
user system elapsed
29.500 0.620 30.125
> system.time(chunk.2(x, n, force.number.of.groups = TRUE))
user system elapsed
5.360 0.300 5.663
注意:将as.factor()更改为as.character()使我的函数速度提高了两倍。
其他回答
如果你不喜欢split()并且你不介意NAs填充你的短尾巴:
chunk <- function(x, n) { if((length(x)%%n)==0) {return(matrix(x, nrow=n))} else {return(matrix(append(x, rep(NA, n-(length(x)%%n))), nrow=n))} }
返回矩阵([,1:ncol])的列是您正在寻找的机器人。
它分成大小为⌊n/k⌋+1或⌊n/k⌋的块,并且不使用O(n log n)排序。
get_chunk_id<-function(n, k){
r <- n %% k
s <- n %/% k
i<-seq_len(n)
1 + ifelse (i <= r * (s+1), (i-1) %/% (s+1), r + ((i - r * (s+1)-1) %/% s))
}
split(1:10, get_chunk_id(10,3))
这里还有另一个,允许你控制你想要的结果是否有序:
split_to_chunks <- function(x, n, keep.order=TRUE){
if(keep.order){
return(split(x, sort(rep(1:n, length.out = length(x)))))
}else{
return(split(x, rep(1:n, length.out = length(x))))
}
}
split_to_chunks(x = 1:11, n = 3)
$`1`
[1] 1 2 3 4
$`2`
[1] 5 6 7 8
$`3`
[1] 9 10 11
split_to_chunks(x = 1:11, n = 3, keep.order=FALSE)
$`1`
[1] 1 4 7 10
$`2`
[1] 2 5 8 11
$`3`
[1] 3 6 9
chunk2 <- function(x,n) split(x, cut(seq_along(x), n, labels = FALSE))
简单的函数通过简单地使用索引来分割一个向量-不需要过于复杂
vsplit <- function(v, n) {
l = length(v)
r = l/n
return(lapply(1:n, function(i) {
s = max(1, round(r*(i-1))+1)
e = min(l, round(r*i))
return(v[s:e])
}))
}