R:复制一行并在每行的下一个日期更新
R: replicate a row and update by next date per row
输入及其预期输出表明我想复制输入行并更新日期条目。我该怎么做?
输入
> aa<- data.frame(a=c(1,11,111),b=c(2,22,222),length=c(3,5,1),date=c(as.Date("28.12.2016",format="%d.%m.%Y"), as.Date("30.12.2016",format="%d.%m.%Y"), as.Date("01.01.2017",format="%d.%m.%Y")))
> aa
a b length date
1 1 2 3 2016-12-28
2 11 22 5 2016-12-30
3 111 222 1 2017-01-01
预期输出
a b length date
1 1 2 3 2016-12-28
2 1 2 3 2016-12-29
3 1 2 3 2016-12-30
4 11 22 5 2016-12-30
5 11 22 5 2016-12-31
6 11 22 5 2017-01-01
7 11 22 5 2017-01-02
8 11 22 5 2017-01-03
9 111 222 1 2017-01-01
不如使用 dplyr 和 data.table 包的优雅,但水平较低:
replicaterow1 <- function(df1 = aa) {
newdf <- df1[0,]
rowss <- nrow(df1)
rowcount <- 1
for (i in 1:rowss) {
rowi <- df1[i,]
reps <- as.integer(rowi[3])
newrow <- rowi
newdf[rowcount,] <- rowi
rowcount <- rowcount + 1
if (reps > 1) {
for(j in 1:(reps-1)) {
newrow[4] <- newrow[4] + 1
newdf[rowcount,] <- newrow
rowcount <- rowcount + 1
}
}
}
return(newdf)
}
这个
aa<- data.frame(a=c(1),b=c(2),length=c(3),date=as.Date("28.12.2016",format="%d.%m.%Y"))
aa <- aa[rep(row.names(aa), aa$length), 1:4]
aa <- as.data.table(aa)
aa[,row:=.I]
aa[,date:=date+row-1]
aa[,row:=NULL]
结果
a b length date
1: 1 2 3 2016-12-28
2: 1 2 3 2016-12-29
3: 1 2 3 2016-12-30
您可以使用 base
、dplyr
或 data.table
进行分组操作。首先重复行以使新数据的大小正确。然后增加天数。
library(dplyr)
aa2 <- aa[rep(1:nrow(aa), aa$length),]
aa2 %>% group_by(a,b) %>% mutate(date= date + 1:n() - 1L)
# Source: local data frame [9 x 4]
# Groups: a, b [3]
#
# a b length date
# <dbl> <dbl> <dbl> <date>
# 1 1 2 3 2016-12-28
# 2 1 2 3 2016-12-29
# 3 1 2 3 2016-12-30
# 4 11 22 5 2016-12-30
# 5 11 22 5 2016-12-31
# 6 11 22 5 2017-01-01
# 7 11 22 5 2017-01-02
# 8 11 22 5 2017-01-03
# 9 111 222 1 2017-01-01
#data.table
library(data.table)
aa2 <- aa[rep(1:nrow(aa), aa$length),]
setDT(aa2)[, date := date + 1:.N - 1L, by= .(a,b)]
#base
aa2 <- aa[rep(1:nrow(aa), aa$length),]
transform(aa2, date=ave(date, a, FUN=function(x) x + 1:length(x) - 1L))
为了更简洁的语法,我们可以利用data.table的回收规则,credit @Henrik:
setDT(aa)[ , .(date = date + 1:length - 1), by = .(a, b)]
输入及其预期输出表明我想复制输入行并更新日期条目。我该怎么做?
输入
> aa<- data.frame(a=c(1,11,111),b=c(2,22,222),length=c(3,5,1),date=c(as.Date("28.12.2016",format="%d.%m.%Y"), as.Date("30.12.2016",format="%d.%m.%Y"), as.Date("01.01.2017",format="%d.%m.%Y")))
> aa
a b length date
1 1 2 3 2016-12-28
2 11 22 5 2016-12-30
3 111 222 1 2017-01-01
预期输出
a b length date
1 1 2 3 2016-12-28
2 1 2 3 2016-12-29
3 1 2 3 2016-12-30
4 11 22 5 2016-12-30
5 11 22 5 2016-12-31
6 11 22 5 2017-01-01
7 11 22 5 2017-01-02
8 11 22 5 2017-01-03
9 111 222 1 2017-01-01
不如使用 dplyr 和 data.table 包的优雅,但水平较低:
replicaterow1 <- function(df1 = aa) {
newdf <- df1[0,]
rowss <- nrow(df1)
rowcount <- 1
for (i in 1:rowss) {
rowi <- df1[i,]
reps <- as.integer(rowi[3])
newrow <- rowi
newdf[rowcount,] <- rowi
rowcount <- rowcount + 1
if (reps > 1) {
for(j in 1:(reps-1)) {
newrow[4] <- newrow[4] + 1
newdf[rowcount,] <- newrow
rowcount <- rowcount + 1
}
}
}
return(newdf)
}
这个
aa<- data.frame(a=c(1),b=c(2),length=c(3),date=as.Date("28.12.2016",format="%d.%m.%Y"))
aa <- aa[rep(row.names(aa), aa$length), 1:4]
aa <- as.data.table(aa)
aa[,row:=.I]
aa[,date:=date+row-1]
aa[,row:=NULL]
结果
a b length date
1: 1 2 3 2016-12-28
2: 1 2 3 2016-12-29
3: 1 2 3 2016-12-30
您可以使用 base
、dplyr
或 data.table
进行分组操作。首先重复行以使新数据的大小正确。然后增加天数。
library(dplyr)
aa2 <- aa[rep(1:nrow(aa), aa$length),]
aa2 %>% group_by(a,b) %>% mutate(date= date + 1:n() - 1L)
# Source: local data frame [9 x 4]
# Groups: a, b [3]
#
# a b length date
# <dbl> <dbl> <dbl> <date>
# 1 1 2 3 2016-12-28
# 2 1 2 3 2016-12-29
# 3 1 2 3 2016-12-30
# 4 11 22 5 2016-12-30
# 5 11 22 5 2016-12-31
# 6 11 22 5 2017-01-01
# 7 11 22 5 2017-01-02
# 8 11 22 5 2017-01-03
# 9 111 222 1 2017-01-01
#data.table
library(data.table)
aa2 <- aa[rep(1:nrow(aa), aa$length),]
setDT(aa2)[, date := date + 1:.N - 1L, by= .(a,b)]
#base
aa2 <- aa[rep(1:nrow(aa), aa$length),]
transform(aa2, date=ave(date, a, FUN=function(x) x + 1:length(x) - 1L))
为了更简洁的语法,我们可以利用data.table的回收规则,credit @Henrik:
setDT(aa)[ , .(date = date + 1:length - 1), by = .(a, b)]