我想要将我的数据从短格式转换成长格式,我想有一种简单的方法可以做到这一点(可能使用reshape2、plyr、dplyr等?)。
例如,我有:
foo <- data.frame(id = 1:5,
y = c(0, 1, 0, 1, 0),
time = c(2, 3, 4, 2, 3))
id y time
1 0 2
2 1 3
3 0 4
4 1 2
5 0 3我想将每行扩展/复制n次,其中n是该行在"time“列中的值。但是,我也希望变量"time“从1递增到n。也就是说,我希望生成:
id y time
1 0 1
1 0 2
2 1 1
2 1 2
2 1 3
3 0 1
3 0 2
3 0 3
3 0 4
4 1 1
4 1 2
5 0 1
5 0 2
5 0 3作为奖励,我还想对变量"y“进行一种递增,其中对于y= 1的I,y被设置为0,直到"time”的最大值。也就是说,我想要产生:
id y time
1 0 1
1 0 2
2 0 1
2 0 2
2 1 3
3 0 1
3 0 2
3 0 3
3 0 4
4 0 1
4 1 2
5 0 1
5 0 2
5 0 3这似乎是dplyr已经在做的事情了,但我只是不知道去哪里看。无论如何,任何避免循环的解决方案都是有帮助的。
发布于 2014-10-02 10:00:09
您可以为长格式创建一个具有适当id和time列的新数据框,然后将其与原始数据框合并。这将为不匹配的值保留NA,然后可以用0替换这些值
merge(foo,
with(foo,
data.frame(id=rep(id,time), time=sequence(time))
),
all.y=TRUE
)
## id time y
## 1 1 1 NA
## 2 1 2 0
## 3 2 1 NA
## 4 2 2 NA
## 5 2 3 1
## 6 3 1 NA
## 7 3 2 NA
## 8 3 3 NA
## 9 3 4 0
## 10 4 1 NA
## 11 4 2 1
## 12 5 1 NA
## 13 5 2 NA
## 14 5 3 0类似的合并适用于第一次扩展。将不带time列的foo与上面创建的数据框合并:
merge(foo[c('id','y')],
with(foo,
data.frame(id=rep(id,time), time=sequence(time))
)
)
## id y time
## 1 1 0 1
## 2 1 0 2
## 3 2 1 1
## 4 2 1 2
## 5 2 1 3
## 6 3 0 1
## 7 3 0 2
## 8 3 0 3
## 9 3 0 4
## 10 4 1 1
## 11 4 1 2
## 12 5 0 1
## 13 5 0 2
## 14 5 0 3没有必要在后一个表达式中指定all (或all.y),因为每个匹配的time值都有多个id值,这些值都被展开了。在前一种情况下,两个数据帧的time值都是匹配的,如果不指定all (或all.y),就会得到原始数据。
发布于 2014-10-02 10:58:31
初始扩展可以通过以下方式实现:
newdat <- transform(
foo[rep(rownames(foo),foo$time),],
time = sequence(foo$time)
)
# id y time
#1 1 0 1
#1.1 1 0 2
#2 2 1 1
#2.1 2 1 2
#2.2 2 1 3
# etc要获得完整的解决方案,包括奖励部分,请执行以下操作:
newdat$y[-cumsum(foo$time)] <- 0
# id y time
#1 1 0 1
#1.1 1 0 2
#2 2 0 1
#2.1 2 0 2
#2.2 2 1 3
#etc如果您真的很兴奋,您可以使用within一步完成所有这些操作
within(
foo[rep(rownames(foo),foo$time),],
{
time <- sequence(foo$time)
y[-cumsum(foo$time)] <- 0
}
)发布于 2014-10-02 12:15:27
如果你愿意使用"data.table",你可以试试:
library(data.table)
fooDT <- as.data.table(foo)
fooDT[, list(time = sequence(time)), by = list(id, y)]
# id y time
# 1: 1 0 1
# 2: 1 0 2
# 3: 2 1 1
# 4: 2 1 2
# 5: 2 1 3
# 6: 3 0 1
# 7: 3 0 2
# 8: 3 0 3
# 9: 3 0 4
# 10: 4 1 1
# 11: 4 1 2
# 12: 5 0 1
# 13: 5 0 2
# 14: 5 0 3还有,关于奖金的问题:
fooDT[, list(time = sequence(time)),
by = list(id, y)][, y := {y[1:(.N-1)] <- 0; y},
by = id][]
# id y time
# 1: 1 0 1
# 2: 1 0 2
# 3: 2 0 1
# 4: 2 0 2
# 5: 2 1 3
# 6: 3 0 1
# 7: 3 0 2
# 8: 3 0 3
# 9: 3 0 4
# 10: 4 0 1
# 11: 4 1 2
# 12: 5 0 1
# 13: 5 0 2
# 14: 5 0 3对于奖金问题,另一个选择是:
fooDT[, list(time=seq_len(time)), by=list(id,y)][y == 1,
y := c(rep.int(0, .N-1L), 1), by=id][]https://stackoverflow.com/questions/26152999
复制相似问题