rdevn00b
rdevn00b

Reputation: 562

Generating a sequence in R

I am working with a list in R that looks like this

[1] 0 0 4 4 0 4 0

now suppose that I want to generate a list of numbers corresponding to this list like this

[[1]]
[1] 1 1

[[2]]
[1] 2 2

[[3]]
[1] 3 6

[[4]]
[1] 7 10

[[5]]
[1] 11 11

[[6]]
[1] 12 15

[[7]]
[1] 16 16

So in other words, the first list gives the groups of a list of a sequence of numbers from 1 to 16 and the second list gives the start and end of each group.

This is probably easier to see if you consider the sequence

1 2 3-6 7-10 11 12-15 16

Is there an easy way to do this? I think I could do it using some sort of global index and lapply but I wanted to see if there were an easier way.

Upvotes: 0

Views: 137

Answers (3)

Josh O'Brien
Josh O'Brien

Reputation: 162451

Here's a slightly different approach:

x <-  c(0,0,3,3,0,3,0)

f <- function(x) {
    ee <- split(seq_len(sum(x+1)), rep.int(seq_along(x), x+1))
    lapply(ee, range)
}
f(x)

Upvotes: 3

Frank
Frank

Reputation: 66819

Here's one way

# alternate input suggested by @MichaelChirico
d = c(0,0,3,3,0,3,0)

# my preferred approach
library(data.table) # version 1.9.5+
Map(c, 
  seq_along(d)+shift(cumsum(d), type="lag", fill=0),
  seq_along(d)+cumsum(d)
)

A similar variation by @akrun:

# alternate input, starting from OP's
d2 = c(0, 0, 4, 4, 0, 4, 0)
d2 = replace( d2, !d2, 1)

# @akrun's answer
Map(c, cumsum(d2)-d2+1, cumsum(d2))

And some more:

# my original answer
start = c(1,head(cumsum(d+1)+1,-1))
Map(c, start, start + d)

# another way
s = sequence(d+1)
Map(c, seq_along(s)[s==1], seq_along(s)[c(diff(s) < 1, TRUE)] )

Upvotes: 4

jeremycg
jeremycg

Reputation: 24945

Here's a function that'll do it, no way near as elegant as @Frank's answer:

mygenerator <- function(vec){
  counter <- 1
  outlist <- list()
  for(i in 1:length(vec)){
    if(vec[i] == 0){
      outlist[[i]] <- c(counter, counter)
      counter <- counter + 1
    } else {
      outlist[[i]] <- c(counter, counter + vec[i] - 1)
      counter <- counter + vec[i]
    }
  }
  outlist
}

mygenerator(c(0, 0, 4, 4, 0, 4, 0))

[[1]]
[1] 1 1

[[2]]
[1] 2 2

[[3]]
[1] 3 6

[[4]]
[1]  7 10

[[5]]
[1] 11 11

[[6]]
[1] 12 15

[[7]]
[1] 16 16

Upvotes: 1

Related Questions