Reputation: 339
How can I repeat a data frame with varying date column at the end? If I apply one of the previously recommended ways, all the columns get repeated. For example:
df<-data.frame(x1=c(1:3), x2=c('z','g','h'), x3=c( rep( as.Date("2011-07-31"), by=1, len=3)) )
n=2
do.call("rbind", replicate(n, df, simplify = FALSE))
x1 x2 x3
1 1 z 2011-07-31
2 2 g 2011-07-31
3 3 h 2011-07-31
4 1 z 2011-07-31
5 2 g 2011-07-31
6 3 h 2011-07-31
Whereas what I need is:
x1 x2 x3
1 1 z 2011-07-31
2 2 g 2011-07-31
3 3 h 2011-07-31
4 1 z 2011-08-01
5 2 g 2011-08-01
6 3 h 2011-08-01
Upvotes: 0
Views: 405
Reputation: 38500
Here is another base R method that works for your example.
# save result
dat <- do.call("rbind", replicate(n, df, simplify = FALSE))
# update x3 variable
dat$x3 <- dat$x3 + cumsum(dat$x1 == 1) - 1
The logic is that we use a cumulative sum that is incremented every time x1 returns to its initial value (here 1). We subtract 1 from the result as we don't want to alter the first block.
this returns
dat
x1 x2 x3
1 1 z 2011-07-31
2 2 g 2011-07-31
3 3 h 2011-07-31
4 1 z 2011-08-01
5 2 g 2011-08-01
6 3 h 2011-08-01
Using transform
, this can be written
transform(dat, x3 = x3 + cumsum(x1 == 1) - 1)
As an alternative counting procedure, we could use seq_len
together with rep
like this
# update x3 variable
dat$x3 <- dat$x3 + rep(seq_len(n)-1L, each=nrow(df))
Upvotes: 0
Reputation: 4335
> n=2
> df1 <- df[rep(1:nrow(df), n),]
> transform(df1, x3=ave(x3, x1, FUN=function(x) x + 1:length(x) - 1L))
x1 x2 x3
1 1 z 2011-07-31
2 2 g 2011-07-31
3 3 h 2011-07-31
1.1 1 z 2011-08-01
2.1 2 g 2011-08-01
3.1 3 h 2011-08-01
or
> library(dplyr)
> df1 <- df[rep(1:nrow(df), n),]
> df1 %>% group_by(x1,x2) %>% mutate(x3= x3 + 1:n() - 1L)
Upvotes: 2