swhat
swhat

Reputation: 493

Transform data frame with set of intervals to set of discrete values

I have a data set where each record has an interval, and I'd like to have the same information but as a set of discrete values within that interval instead.

Example: Input data frame

  start end val
1     2   4   a
2     2   5   b
3     1   3   c

Output data frame

  time val
1    2   a
2    3   a
3    4   a
4    2   b
5    3   b
6    4   b
7    5   b
8    1   c
9    2   c
10   3   c

What's a good way to accomplish that sort of transformation? Additionally, the val column could be multiple columns to repeat in the same pattern.

Upvotes: 0

Views: 97

Answers (2)

markus
markus

Reputation: 26343

Here is a data.table solution

library(data.table)
setDT(df)[, .(time = seq(start, end)), by = val][]
#    val time
# 1:   a    2
# 2:   a    3
# 3:   a    4
# 4:   b    2
# 5:   b    3
# 6:   b    4
# 7:   b    5
# 8:   c    1
# 9:   c    2
#10:   c    3

data

df <- structure(list(start = c(2L, 2L, 1L), end = c(4L, 5L, 3L), val = c("a", 
"b", "c")), .Names = c("start", "end", "val"), class = "data.frame", row.names = c("1", 
"2", "3"))

Upvotes: 1

Gregor Thomas
Gregor Thomas

Reputation: 145785

Here's one way:

dd$time = Map(f = seq, dd$start, dd$end)
tidyr::unnest(dd[c("val", "time")])
#    val time
# 1    a    2
# 2    a    3
# 3    a    4
# 4    b    2
# 5    b    3
# 6    b    4
# 7    b    5
# 8    c    1
# 9    c    2
# 10   c    3

Using this sample data:

dd = read.table(text = "start end val
1     2   4   a
2     2   5   b
3     1   3   c", header = TRUE)

Upvotes: 2

Related Questions