【问题标题】:Sum of neighboring columns based on conditions基于条件的相邻列的总和
【发布时间】:2019-12-05 14:19:24
【问题描述】:

我试图从我的第一个值大于零的列开始,准确地总结四个相邻列中的值。 IE。当 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 行,我真的很感激能以优雅的方式来做这件事。

非常感谢!

【问题讨论】:

    标签: r sum


    【解决方案1】:

    也许你可以使用下面的代码

    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))
    

    【讨论】:

    • 感谢您的解决方案。它也适用于我的原始数据集。我可以在您的代码中选择特定列吗?因为我不想考虑我的所有列进行计算(例如,名称列应该被忽略)。或者我只能通过构建一个只选择带有数字的列的子集来解决这个问题吗?
    • @ZayzayR 好吧,我认为最好对要使用的列进行子集化,然后在选定的列上应用代码。否则,整合列选择的过程会增加代码复杂度,也不利于处理
    【解决方案2】:

    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. 它在参数末尾使用“sentinel”0 来保证which.min 返回非空值。

    2. 它依赖于R 为超出有效范围的索引返回NA 值。这些在随后对sum 的调用中被明确忽略。

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

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

    【讨论】:

      【解决方案3】:

      这里有一个带有max.col的选项,用于查找每行中第一个非零值的列位置,通过使用@创建rowcolumn索引('i','j') 987654324@,提取数据集中的值,得到按'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))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-10-24
        • 2013-03-21
        • 2017-08-13
        • 2017-12-30
        • 1970-01-01
        • 2021-11-05
        • 2017-05-28
        相关资源
        最近更新 更多