R split numeric vector at position

ID : 274346

viewed : 38

Tags : rvectorsplitr





Top 4 Answer for R split numeric vector at position

vote vote

96

An improvement would be:

splitAt <- function(x, pos) unname(split(x, cumsum(seq_along(x) %in% pos))) 

which can now take a vector of positions:

splitAt(a, c(2, 4)) # [[1]] # [1] 1 #  # [[2]] # [1] 2 2 #  # [[3]] # [1] 3 

And it does behave properly (subjective) if pos <= 0 or pos >= length(x) in the sense that it returns the whole original vector in a single list item. If you'd like it to error out instead, use stopifnot at the top of the function.

vote vote

90

I tried to use flodel's answer, but it was too slow in my case with a very large x (and the function has to be called repeatedly). So I created the following function that is much faster, but also very ugly and doesn't behave properly. In particular, it doesn't check anything and will return buggy results at least for pos >= length(x) or pos <= 0 (you can add those checks yourself if you're unsure about your inputs and not too concerned about speed), and perhaps some other cases as well, so be careful.

splitAt2 <- function(x, pos) {     out <- list()     pos2 <- c(1, pos, length(x)+1)     for (i in seq_along(pos2[-1])) {         out[[i]] <- x[pos2[i]:(pos2[i+1]-1)]     }     return(out) } 

However, splitAt2 runs about 20 times faster with an x of length 106:

library(microbenchmark) W <- rnorm(1e6) splits <- cumsum(rep(1e5, 9)) tm <- microbenchmark(                      splitAt(W, splits),                      splitAt2(W, splits),                      times=10) tm 
vote vote

73

Another alternative that might be faster and/or more readable/elegant than flodel's solution:

splitAt <- function(x, pos) {   unname(split(x, findInterval(x, pos))) } 
vote vote

66

Top 3 video Explaining R split numeric vector at position







Related QUESTION?