我有一个名为(df)的数据框,其结构如下:
day colA colB
1 4 8
2 9 2
3 8 1
4 9 4
1 5 8
2 2 4
问题:
我想创建一个名为'colC'的新列,其逻辑如下:
if day is equal to 1, then colC = colA+colB
if day not equal to 1, then colC = (colA+colB) - previous ColC
预期解决方案:
day colA colB colC
1 4 8 12
2 9 2 -1
3 8 1 10
4 9 4 3
1 5 8 13
2 2 4 -7
当前解决方案:
for(i in 1:NROW(df)
{
if(day[i] == 1) {colC[i] <- colA[i] + colB[i]}
else {colC[i] <- colA[i] + colB[i] - colC[i-1]}
}
问题:
答案 0 :(得分:0)
我有一个使用移位的解决方案,并在两行之间的最大距离上循环== 1
df$colC = df$colA + df$colB
for (i in 1:max(diff(which(df$day == 1))))
{
df$colCshift = c(NA,df$colC[1:(length(df$colC)-1)]) # creating a shifted version of colC
df$colC[df$day != 1] = df$colA[df$day != 1] + df$colB[df$day != 1] - df$colCshift[df$day != 1]
# here colC[i-1] is the shifted version of ColC.
}
day colA colB colC colCshift
1 1 4 8 12 NA
2 2 9 2 -1 12
3 3 8 1 10 -1
4 4 9 4 3 10
5 1 5 8 13 3
6 2 2 4 -7 13
第一次迭代正确计算数据框中各处的所有行。然后我更新了colC的移位版本,并在day = 1之后计算所有行两行等等。
此处max(diff(which(df$day == 1)))
应该是您所说的
答案 1 :(得分:0)
这应该很快。您需要包dplyr
。
df$colC <- df$colA+df$colB
df$colD <- dplyr::lag(df$colC,1)
df$colC <- ifelse(df$day != 1, df$colC-df$colD, df$colC)
> df[, 1:4]
day colA colB colC
1 1 4 8 12
2 2 9 2 -1
3 3 8 1 -2
4 4 9 4 4
5 1 5 8 13
6 2 2 4 -7
顺便说一下,你的预期输出似乎是假的。
答案 2 :(得分:0)
您的数据:
df <- structure(list(day = c(1L, 2L, 3L, 4L, 1L, 2L), colA = c(4L,
9L, 8L, 9L, 5L, 2L), colB = c(8L, 2L, 1L, 4L, 8L, 4L)), .Names = c("day",
"colA", "colB"), class = "data.frame", row.names = c(NA, -6L))
起始案例:
df$colC <- df$colA + df$colB
我建议不要使用for
进行循环,而是使用cumsum(df$day == 1)
声明每个天数。从那里,我们可以使用Reduce
的技巧来进行滚动应用:
df <- do.call(rbind, by(df, cumsum(df$day == 1), function(d) {
d$colC <- Reduce(function(a,b) b-a, d$colC[-1], d$colC[1], accumulate=T)
d
}))
我认为您在第5行的预期输出不正确,因为它5+8
只是day==1
。
df
# day colA colB colC
# 1.1 1 4 8 12
# 1.2 2 9 2 -1
# 1.3 3 8 1 10
# 1.4 4 9 4 3
# 2.5 1 5 8 13
# 2.6 2 2 4 -7
编辑:我认为您应该将代码更新为以群组为中心而不是以行为中心,但由于您认为需要使用for
,请从原始{开始{1}}:
df
或许(稍微更快):
df$colC <- df$colA + df$colB
for (i in seq_len(nrow(df))) {
df$colC[i] <- df$colC[i] - ifelse(i < 2 | df$day[i] == 1, 0, df$colC[i-1])
}