我试图对四个相邻列中的值求和,从第一个值大于零的列开始。即当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行,所以我非常欣赏一种优雅的方法。
非常感谢您!
答案 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
依靠两种值得注意的技术:
它在参数末尾使用“前哨” 0来保证which.min
返回非空值。
它依靠R
返回NA
值来获取超出有效范围的索引。在随后的对sum
的调用中,这些内容被明确忽略。
如果要在一行中至少没有四个值求和时返回某种错误或警告,则需要修改f
。
最后,stopifnot
单元测试将测试参数的列表传递到f
(大多数是“边缘情况”)以及这些情况的预期值列表。它将f
应用于每个自变量,并将其结果与预期值进行比较。如果有任何差异,R
将暂停执行。这有助于确保您得到想要的结果。
答案 1 :(得分:0)
这里是max.col
的一个选项,用于查找每行中第一个非零值的列位置,创建row
和column
索引('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))