在数据框中,按行计算超过某个值的列数

4

我正在使用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开头且不是NA的列数。对于Count2也是同样的情况,但使用Limit2。我的数据框的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")

非常感谢您的帮助。
3个回答

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

按照要求。

1
如果您有一个大的数据框,我建议您避免逐行操作,而是只需运行与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))
          ]

0

您正在使用的代码有些问题,这是修复问题的方法:

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

在应用函数时,x是您正在操作的行,将其与Base [8]进行比较实际上是将一行与Base [8]进行比较,这就是答案错误的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接