简体   繁体   中英

How do I split a vector into a list of vectors when a condition is met?

I would like to split a vector of into a list of vectors. The resulting vectors will be of variable length, and I need the split to occur only when certain conditions are met.

Sample data:

set.seed(3)
x <- sample(0:9,100,repl=TRUE)

For example, in this case I would like to split the above vector x at each 0.

Currently I do this with my own function:

ConditionalSplit <- function(myvec, splitfun) {
  newlist <- list()
  splits <- which(splitfun(x))
  if (splits == integer(0)) return(list(myvec))
  if (splits[1] != 1) newlist[[1]] <- myvec[1:(splits[1]-1)]
  i <- 1
  imax <- length(splits)

  while (i < imax) {
    curstart <- splits[i]
    curend <- splits[i+1]
    if (curstart != curend - 1)
      newlist <- c(newlist, list(myvec[curstart:(curend-1)]))
    i <- i + 1
  }

  newlist <- c(newlist, list(myvec[splits[i]:length(vector)]))
  return(newlist)
}

This function gives the output I'd like, but I'm certain there's a better way than mine.

> MySplit <- function(x) x == 0

> ConditionalSplit(x, MySplit)

[[1]]
 [1] 1 8 3 3 6 6 1 2 5 6 5 5 5 5 8 8 1 7 8 2 2

[[2]]
[1] 0 1

[[3]]
 [1] 0 2 7 5 9 5 7 3 3 1 4 2 3 8 2 5 2 2 7 1 5 4 2
...

以下行似乎工作得很好:

split(x,cumsum(x==0))

Another solution is to use tapply. A good reason to use tapply instead of split is because it lets you perform other operations on the items in the list while you're splitting it.

For example, in this solution to the question:

> x <- sample(0:9,100,repl=TRUE)
> idx <- cumsum(x==0)
> splitList <- tapply(x, idx, function(y) {list(y)})
> splitList
$`0`
[1] 2 9 2

$`1`
[1] 0 5 5 3 8 4

$`2`
[1] 0 2 5 2 6 2 2

$`3`
[1] 0 8 1 7 5

$`4`
 [1] 0 1 6 6 3 8 7 2 4 2 3 1

$`5`
[1] 0 6 8 9 9 1 1 2

$`6`
 [1] 0 1 2 2 2 7 8 1 9 7 9 3 4 8 4 6 4 5 3 1

$`7`
[1] 0 2 7 8 5

$`8`
[1] 0 3 4 8 4 7 3

$`9`
[1] 0 8 4

$`10`
 [1] 0 4 3 9 9 8 7 4 4 5 5 1 1 7 3 9 7 4 4 7 7 6 3 3

Can be modified so that you divide each element by the number of elements in that list.

list(y/length(y))

instead of

list(y)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM