我必须在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

当前回答

如果你不喜欢split(),也不喜欢matrix()(它的悬垂NAs),有这样的:

chunk <- function(x, n) (mapply(function(a, b) (x[a:b]), seq.int(from=1, to=length(x), by=n), pmin(seq.int(from=1, to=length(x), by=n)+(n-1), length(x)), SIMPLIFY=FALSE))

与split()一样,它返回一个列表,但它不会在标签上浪费时间或空间,因此性能可能更高。

其他回答

还有更多的变种…

> x <- 1:10
> n <- 3

注意,这里你不需要使用因子函数,但你仍然想要排序,你的第一个向量将是1 2 3 10:

> chunk <- function(x, n) split(x, sort(rank(x) %% n))
> chunk(x,n)
$`0`
[1] 1 2 3
$`1`
[1] 4 5 6 7
$`2`
[1]  8  9 10

或者你可以指定字符索引,替换上面左边的数字:

> my.chunk <- function(x, n) split(x, sort(rep(letters[1:n], each=n, len=length(x))))
> my.chunk(x, n)
$a
[1] 1 2 3 4
$b
[1] 5 6 7
$c
[1]  8  9 10

或者您可以使用存储在vector中的纯字名称。注意,使用sort来获取x中的连续值会使标签按字母顺序排列:

> my.other.chunk <- function(x, n) split(x, sort(rep(c("tom", "dick", "harry"), each=n, len=length(x))))
> my.other.chunk(x, n)
$dick
[1] 1 2 3
$harry
[1] 4 5 6
$tom
[1]  7  8  9 10

简单的函数通过简单地使用索引来分割一个向量-不需要过于复杂

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])
    }))
}

这是另一种变体。

注意:在这个示例中,您在第二个参数中指定CHUNK SIZE

所有的块都是均匀的,除了最后一块; 最后一个最坏的情况是更小,永远不会比块大小大。

chunk <- function(x,n)
{
    f <- sort(rep(1:(trunc(length(x)/n)+1),n))[1:length(x)]
    return(split(x,f))
}

#Test
n<-c(1,2,3,4,5,6,7,8,9,10,11)

c<-chunk(n,5)

q<-lapply(c, function(r) cat(r,sep=",",collapse="|") )
#output
1,2,3,4,5,|6,7,8,9,10,|11,|

它分成大小为⌊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(),也不喜欢matrix()(它的悬垂NAs),有这样的:

chunk <- function(x, n) (mapply(function(a, b) (x[a:b]), seq.int(from=1, to=length(x), by=n), pmin(seq.int(from=1, to=length(x), by=n)+(n-1), length(x)), SIMPLIFY=FALSE))

与split()一样,它返回一个列表,但它不会在标签上浪费时间或空间,因此性能可能更高。