基于条件的相邻列的总和

时间:2019-12-05 14:19:24

标签: r sum

我试图对四个相邻列中的值求和,从第一个值大于零的列开始。即当x1列中的值是0而x2中的值是1时,我想得到x2,x3,x4,x5的总和。让我们假设以下示例:

df<- data.frame(x1=c(1,0,0), x2=c(0,3,0), x3=c(1,2,2), x4=c(3,4,4), x5=c(3,3,3), x6=c(3,4,5))

x1  x2  x3  x4  x5  x6
1   0   1   3   3   3
0   3   2   4   3   4
0   0   2   4   3   5

在第一行中,总和应从第一个值开始,因为这是该行中大于零的第一个值。然后应该采用四个连续的列,即x1 + x2 + x3 + x4。在第二行中,总和应从第二个值开始,因此总和应为x2 + x3 + x4 + x5。在第三行中,总和应以x3开头,得出x3 + x4 + x5 + x6。

所以我最后想要得到的是一列包含四个连续求和的列:

x1  x2  x3  x4  x5  x6  Sum
1   0   1   3   3   3    5
0   3   2   4   3   4    12
0   0   2   4   3   5    14

因为我有近40列和300行,所以我非常欣赏一种优雅的方法。

非常感谢您!

3 个答案:

答案 0 :(得分:0)

which函数家族将标识第一个非零。循环的方法有多种:查看*apply系列。

这是一个经过测试的解决方案。

f <- function(x) {
  i <- which.min(c(x,0)==0)
  sum(x[i+0:3], na.rm=TRUE)
}
#
# Test f.
#
stopifnot(mapply(function(x,y) f(x)==y,
       list(c(), 0, 1, c(1,NA), c(1,1), NA),
       c(0,0,1,1,2,0)))
#
# Do the calculation.
#
df<- data.frame(x1=c(1,0,0), x2=c(0,3,0), x3=c(1,2,2), x4=c(3,4,4), x5=c(3,3,3), x6=c(3,4,5))
df$Sum <- apply(df, 1, f)

(df)
x1 x2 x3 x4 x5 x6 Sum
1  1  0  1  3  3  3   5
2  0  3  2  4  3  4  12
3  0  0  2  4  3  5  14

核心功能f依靠两种值得注意的技术:

  1. 它在参数末尾使用“前哨” 0来保证which.min返回非空值。

  2. 它依靠R返回NA值来获取超出有效范围的索引。在随后的对sum的调用中,这些内容被明确忽略。

如果要在一行中至少没有四个值求和时返回某种错误或警告,则需要修改f

最后,stopifnot单元测试将测试参数的列表传递到f(大多数是“边缘情况”)以及这些情况的预期值列表。它将f应用于每个自变量,并将其结果与预期值进行比较。如果有任何差异,R将暂停执行。这有助于确保您得到想要的结果。

答案 1 :(得分:0)

这里是max.col的一个选项,用于查找每行中第一个非零值的列位置,创建rowcolumn索引('i','j' ),使用rep提取数据集中的值,并获取按“ i”列分组的sum

j <- max.col(df >0, 'first')
j <- j + rep(0:3, each = length(j))
i <- rep(seq_len(nrow(df)), 4)
df$Sum <- tapply(df[cbind(i, j)], i, FUN = sum)
df
#  x1 x2 x3 x4 x5 x6 Sum
#1  1  0  1  3  3  3   5
#2  0  3  2  4  3  4  12
#3  0  0  2  4  3  5  14

数据

df <- structure(list(x1 = c(1, 0, 0), x2 = c(0, 3, 0), x3 = c(1, 2, 
2), x4 = c(3, 4, 4), x5 = c(3, 3, 3), x6 = c(3, 4, 5)), 
class = "data.frame", row.names = c(NA, 
-3L))

答案 2 :(得分:0)

也许您可以使用以下代码

df$Sum <- sapply(1:nrow(df), function(k) sum(df[k,head(which(df[k,]>0),1) + 0:3]))

给出:

> df
  x1 x2 x3 x4 x5 x6 Sum
1  1  0  1  3  3  3   5
2  0  3  2  4  3  4  12
3  0  0  2  4  3  5  14

数据

df <- structure(list(x1 = c(1, 0, 0), x2 = c(0, 3, 0), x3 = c(1, 2,2), x4 = c(3, 4, 4), x5 = c(3, 3, 3), x6 = c(3, 4, 5)), 
                class = "data.frame", row.names = c(NA, -3L))