按行计算超过数据框中值的列数
Count number of columns by row that exceed a value in dataframe
我在 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
。我的 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")
非常感谢您的帮助。
您使用的代码有点不对,这解决了问题:
apply(Base[c(2:7, 8)],1,function(x) length(which(x>tail(x, 1) & !is.na(x))))
因为在应用函数时,x
是你操作的行,与Base[8]
比较实际上是与Base[8]
比较行,这就是答案所在关闭。
我建议类似
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
随心所欲。
如果你有一个大数据框,我建议你避免按行这样做,而只是 运行 这是你必须比较的 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))
]
我在 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
。我的 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")
非常感谢您的帮助。
您使用的代码有点不对,这解决了问题:
apply(Base[c(2:7, 8)],1,function(x) length(which(x>tail(x, 1) & !is.na(x))))
因为在应用函数时,x
是你操作的行,与Base[8]
比较实际上是与Base[8]
比较行,这就是答案所在关闭。
我建议类似
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
随心所欲。
如果你有一个大数据框,我建议你避免按行这样做,而只是 运行 这是你必须比较的 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))
]