【问题标题】:Count number of columns by row that exceed a value in dataframe逐行计算超过数据框中值的列数
【发布时间】:2015-02-02 22:12:49
【问题描述】:

我正在使用 R 中的一个大数据框,我需要按每一行计算超出数据框另一个变量中保存的限制的列数。我的数据框Base 看起来像这样(我在最后一面添加了dput() 版本):

    ID NT1 NT2 NT3 NT4 NT5 NT6 Limit1 Limit2
1  001   1   1   1  NA  NA  NA      2      3
2  002   2   1   5   4  NA  NA      2      3
3  003   3  NA   1  NA   1  NA      2      3
4  004   3  NA   3  NA   8  NA      2      3
5  005   4   5   1  NA  NA  NA      4      5
6  006   9   9   9  NA  NA   8      8      9
7  007   1   3   5   9  NA  NA      5      4
8  008  NA  NA   6   7   9   8      6      5
9  009   1   1  NA  NA  NA  NA      1      2
10 010   3   4   5   5   5   5      2      2

我需要计算名称以NT 开头的列并且超出了名为Limit1 的列。该值必须保存在另一列中。 Limit2 的情况相同,我必须计算以 NT 开头并超过 Limit2 的值的列。此外,结果必须保存在新列中。我已经尝试使用下一个代码,但它不起作用:

Base$Count1=apply(Base[c(2:7,8)],1,function(x) length(which(x>Base[8] & !is.na(x))))

此外,重要的事实是,Base 是一个包含 200000 行和 60 列的大数据框的样本。出于这个原因,我的apply 测试没有完成或者我出错了。我想得到这样的结果:

    ID NT1 NT2 NT3 NT4 NT5 NT6 Limit1 Limit2 Count1 Count2
1  001   1   1   1  NA  NA  NA      2      3      0      0
2  002   2   1   5   4  NA  NA      2      3      2      2
3  003   3  NA   1  NA   1  NA      2      3      1      0
4  004   3  NA   3  NA   8  NA      2      3      3      1
5  005   4   5   1  NA  NA  NA      4      5      1      0
6  006   9   9   9  NA  NA   8      8      9      3      0
7  007   1   3   5   9  NA  NA      5      4      1      2
8  008  NA  NA   6   7   9   8      6      5      3      4
9  009   1   1  NA  NA  NA  NA      1      2      0      0
10 010   3   4   5   5   5   5      2      2      6      6

其中Count1 保存超过Limit1 的列数,以NT 开头,而不是NACount2 相同,但使用 Limit2。我的datafrmae 的dput() 版本是下一个:

Base<-structure(list(ID = c("001", "002", "003", "004", "005", "006", 
"007", "008", "009", "010"), NT1 = c(1, 2, 3, 3, 4, 9, 1, NA, 
1, 3), NT2 = c(1, 1, NA, NA, 5, 9, 3, NA, 1, 4), NT3 = c(1, 5, 
1, 3, 1, 9, 5, 6, NA, 5), NT4 = c(NA, 4, NA, NA, NA, NA, 9, 7, 
NA, 5), NT5 = c(NA, NA, 1, 8, NA, NA, NA, 9, NA, 5), NT6 = c(NA, 
NA, NA, NA, NA, 8, NA, 8, NA, 5), Limit1 = c(2, 2, 2, 2, 4, 8, 
5, 6, 1, 2), Limit2 = c(3, 3, 3, 3, 5, 9, 4, 5, 2, 2)), .Names = c("ID", 
"NT1", "NT2", "NT3", "NT4", "NT5", "NT6", "Limit1", "Limit2"), row.names = c(NA, 
-10L), class = "data.frame")

非常感谢您的帮助。

【问题讨论】:

    标签: r data.table dplyr


    【解决方案1】:

    我建议类似

    Base$Count1 <- rowSums(Base[,grep("^NT", names(Base))] > Base$Limit1, na.rm=T)
    Base$Count2 <- rowSums(Base[,grep("^NT", names(Base))] > Base$Limit2, na.rm=T)
    

    这会产生

        ID NT1 NT2 NT3 NT4 NT5 NT6 Limit1 Limit2 Count1 Count2
    1  001   1   1   1  NA  NA  NA      2      3      0      0
    2  002   2   1   5   4  NA  NA      2      3      2      2
    3  003   3  NA   1  NA   1  NA      2      3      1      0
    4  004   3  NA   3  NA   8  NA      2      3      3      1
    5  005   4   5   1  NA  NA  NA      4      5      1      0
    6  006   9   9   9  NA  NA   8      8      9      3      0
    7  007   1   3   5   9  NA  NA      5      4      1      2
    8  008  NA  NA   6   7   9   8      6      5      3      4
    9  009   1   1  NA  NA  NA  NA      1      2      0      0
    10 010   3   4   5   5   5   5      2      2      6      6
    

    根据需要。

    【讨论】:

      【解决方案2】:

      如果您有一个大数据框,我建议您避免逐行执行此操作,而只需运行您必须比较的 Limit 列的数量

      sapply(grep("Limit", names(df), value = TRUE), 
              function(x) rowSums(df[grepl("^NT", names(df))] > df[, x], 
              na.rm = TRUE))
      
      #    Limit1 Limit2
      # 1       0      0
      # 2       2      2
      # 3       1      0
      # 4       3      1
      # 5       1      0
      # 6       3      0
      # 7       1      2
      # 8       3      4
      # 9       0      0
      # 10      6      6
      

      如果您想使用data.table 执行此操作,您可以通过引用更新您的列,使用

      library(data.table)
      setDT(df)[, c("Count1", "Count2") := 
                  lapply(grep("Limit", names(df), value = TRUE),
                         function(x) rowSums(.SD[, 
                           grepl("^NT", names(df)), with = FALSE] > 
                           .SD[[x]], na.rm = TRUE))
                ]
      

      【讨论】:

        【解决方案3】:

        您使用的代码有点不对劲,这解决了问题:

        apply(Base[c(2:7, 8)],1,function(x) length(which(x>tail(x, 1) & !is.na(x))))
        

        由于在应用函数时,x 是您正在操作的行,将其与 Base[8] 比较实际上是将行与 Base[8] 进行比较,这就是答案不成立的地方。

        【讨论】:

          猜你喜欢
          • 2022-11-30
          • 2019-01-29
          • 1970-01-01
          • 2017-12-29
          • 2021-06-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多