Split a vector into chunks in R

2018-12-31 06:53发布

I have to split a vector into n chunks of equal size in R. I couldn't find any base function to do that. Also Google didn't get me anywhere. So here is what I came up with, hopefully it helps someone some where.

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

Any comments, suggestions or improvements are really welcome and appreciated.

Cheers, Sebastian

标签: r vector
19条回答
泪湿衣
2楼-- · 2018-12-31 07:37

You could combine the split/cut, as suggested by mdsummer, with quantile to create even groups:

split(x,cut(x,quantile(x,(0:n)/n), include.lowest=TRUE, labels=FALSE))

This gives the same result for your example, but not for skewed variables.

查看更多
冷夜・残月
3楼-- · 2018-12-31 07:37

Sorry if this answer comes so late, but maybe it can be useful for someone else. Actually there is a very useful solution to this problem, explained at the end of ?split.

> testVector <- c(1:10) #I want to divide it into 5 parts
> VectorList <- split(testVector, 1:5)
> VectorList
$`1`
[1] 1 6

$`2`
[1] 2 7

$`3`
[1] 3 8

$`4`
[1] 4 9

$`5`
[1]  5 10
查看更多
十年一品温如言
4楼-- · 2018-12-31 07:41

split(x,matrix(1:n,n,length(x))[1:length(x)])

perhaps this is more clear, but the same idea:
split(x,rep(1:n, ceiling(length(x)/n),length.out = length(x)))

if you want it ordered,throw a sort around it

查看更多
十年一品温如言
5楼-- · 2018-12-31 07:41

Credit to @Sebastian for this function

chunk <- function(x,y){
         split(x, factor(sort(rank(row.names(x))%%y)))
         }
查看更多
公子世无双
6楼-- · 2018-12-31 07:44

Here's another variant.

NOTE: with this sample you're specifying the CHUNK SIZE in the second parameter

  1. all chunks are uniform, except for the last;
  2. the last will at worst be smaller, never bigger than the 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,|
查看更多
查无此人
7楼-- · 2018-12-31 07:44

Wow, this question got more traction than expected.

Thanks for all the ideas. I have come up with this solution:

require(magrittr)
create.chunks <- function(x, elements.per.chunk){
    # plain R version
    # split(x, rep(seq_along(x), each = elements.per.chunk)[seq_along(x)])
    # magrittr version - because that's what people use now
    x %>% seq_along %>% rep(., each = elements.per.chunk) %>% extract(seq_along(x)) %>% split(x, .) 
}
create.chunks(letters[1:10], 3)
$`1`
[1] "a" "b" "c"

$`2`
[1] "d" "e" "f"

$`3`
[1] "g" "h" "i"

$`4`
[1] "j"

The key is to use the seq(each = chunk.size) parameter so make it work. Using seq_along acts like rank(x) in my previous solution, but is actually able to produce the correct result with duplicate entries.

查看更多
登录 后发表回答