使用
df <- data.frame(id=c(1:5), v1=c(0,15,9,12,7), v2=c(9,32,6,17,11))
如何在大于10的所有列上提取值,并返回:
id v1 v2
2 2 15 32
4 4 12 17
如果在任何大于10的列上,该怎么办?
id v1 v2
2 2 15 32
4 4 12 17
5 5 7 11
答案 0 :(得分:19)
分别针对问题的第一部分和第二部分查看函数all()
和any()
。 apply()
函数可用于在行或列上运行函数。 (MARGIN = 1
是行,MARGIN = 2
是列等)。注意我在apply()
上使用df[, -1]
在进行比较时忽略id
变量。
第1部分:
> df <- data.frame(id=c(1:5), v1=c(0,15,9,12,7), v2=c(9,32,6,17,11))
> df[apply(df[, -1], MARGIN = 1, function(x) all(x > 10)), ]
id v1 v2
2 2 15 32
4 4 12 17
第2部分:
> df[apply(df[, -1], MARGIN = 1, function(x) any(x > 10)), ]
id v1 v2
2 2 15 32
4 4 12 17
5 5 7 11
要查看正在进行的操作,x > 10
会为每一行返回一个逻辑向量(通过apply()
指示每个元素是否大于10. all()
返回TRUE
如果输入向量的所有元素都是TRUE
和FALSE
否则。any()
如果任何元素,则返回TRUE
输入中的TRUE
和FALSE
如果全部为FALSE
。
然后我使用apply()
调用
> apply(df[, -1], MARGIN = 1, function(x) all(x > 10))
[1] FALSE TRUE FALSE TRUE FALSE
> apply(df[, -1], MARGIN = 1, function(x) any(x > 10))
[1] FALSE TRUE FALSE TRUE TRUE
到子集df
(如上所示)。
答案 1 :(得分:6)
这可以使用带有边距1的apply
来完成,这会将函数应用于每一行。检查给定行的函数是
function(row) {all(row > 10)}
所以提取行本身的方法是
df[apply(df, 1, function(row) {all(row > 10)}),]
答案 2 :(得分:2)
一个选项是逐行循环(例如使用apply
)并使用any
或all
,如其他两个答案中所建议的那样。但是,对于大型数据帧,这可能效率低下。
矢量化方法是使用rowSums
来确定符合条件的每一行中的值的数量,并根据该值进行过滤。
当过滤到一切都至少为10的行时,这与过滤到不超过10的值的数量为0的情况相同:
df[rowSums(df[,-1] <= 10) == 0,]
# id v1 v2
# 2 2 15 32
# 4 4 12 17
同样,rowSums
可以很容易地用于计算任何超过10的行:
df[rowSums(df[,-1] > 10) > 0,]
# id v1 v2
# 2 2 15 32
# 4 4 12 17
# 5 5 7 11
输入较大时加速很明显:
set.seed(144)
df <- matrix(sample(c(1, 10, 20), 3e6, replace=TRUE), ncol=3)
system.time(df[apply(df[, -1], MARGIN = 1, function(x) all(x > 10)), ])
# user system elapsed
# 1.754 0.156 2.102
system.time(df[rowSums(df[,-1] <= 10) == 0,])
# user system elapsed
# 0.04 0.01 0.05
答案 3 :(得分:1)
dplyr
等价物如下
library(dplyr)
#ANY
df %>% rowwise() %>%
filter(any(across(starts_with("v"), ~ sum((. > 10)))))
# A tibble: 3 x 3
# Rowwise:
id v1 v2
<int> <dbl> <dbl>
1 2 15 32
2 4 12 17
3 5 7 11
#ALL
df %>% rowwise() %>%
filter(all(across(starts_with("v"), ~ sum((. > 10)))))
# A tibble: 2 x 3
# Rowwise:
id v1 v2
<int> <dbl> <dbl>
1 2 15 32
2 4 12 17