2017-08-25 89 views
2

我想在不同列上使用相同条件来选择行。在多个列上过滤具有相同条件的行

set.seed(123) 
df <- data.frame(col.x = sample(LETTERS[1:10], 20, replace = TRUE), 
       col.y = sample(LETTERS[1:10], 20, replace = TRUE), 
       val = rnorm(20)) 

我需要跨两列col.xcol.y只有在ValsToRetain值。

ValsToRetain <- c('A','D', 'F','H','J') 

我试过这两种方法给出相同的预期输出。

df %>% filter(col.x %in% ValsToRetain) %>% filter(col.y %in% ValsToRetain) 
df %>% filter(col.x %in% ValsToRetain & col.y %in% ValsToRetain) 
# col.x col.y  val 
# 1  A  H -1.6866933 
# 2  F  F 0.8377870 
# 3  J  J 0.4264642 
# 4  F  H 0.8781335 
# 5  D  D -0.3059627 

但是,有没有其他优雅的方式来做到这一点?

例如;例如在这些列中计算rowSums以检查它是否有na s。由于有多个价值,我无法得到类似的想法,如rowSums(df[,1:2] == 'A')

回答

3

我们可以使用filter_atall_vars

df %>% 
    filter_at(vars(starts_with("col")), all_vars(. %in% ValsToRetain)) 
# col.x col.y  val 
#1  A  H -1.6866933 
#2  F  F 0.8377870 
#3  J  J 0.4264642 
#4  F  H 0.8781335 
#5  D  D -0.3059627 
+0

谢谢,这绝对是一个优雅的方式。你看到其他的方法,如果col的名字是'xvar','yvar' ,'valvar'?它是'filter_at(vars('xvar','yvar'),all_vars(。%in%ValsToRetain))'??顺便说一下,你正在使用哪个版本的'dplyr'?我得到一个错误'无法找到函数“filter_at”'。 – Prradep

+2

您可以使用否定版本的变量,即'df%>%filter_at(变量(-val),all_vars(%在%ValsToRetain)中)' – Sotos

-1

您可以使用子集,它很短,但同样的方式比你的方法:

filt <- subset(df,col.x %in% ValsToRetain & col.y %in% ValsToRetain) 

输出是:

col.x col.y  val 
    A  H -1.6866933 
    F  F 0.8377870 
    J  J 0.4264642 
    F  H 0.8781335 
    D  D -0.3059627 
+0

这与OP的第二个选项* df%>%filter完全相同(%%ValsToRetain&col.y%in%ValsToRetain)中的col.x%* - 您刚刚使用'subset'而不是'filter' – Sotos

+0

@Sotos这正是我所说的“与您的方法相同的方式”我必须投入downvote我猜 –

+1

嗯,我觉得downvote在这里是合理的,因为OP寻求*任何其他优雅的方式来做到这一点* ...我的意思是你可以更新不同的东西,至少给一些对您的答案有价值,我会很乐意推翻我的投票。例如'df%>%mutate_at(vars(-val),funs((替换(。,!。%in%ValsToRetain,NA))))%>%na.omit()' – Sotos

1

这里是使用Reduce和的基本R方法。 lapply跨相关列应用%in%,返回逻辑向量列表。然后Reduce使用&将这些载体组合成单个载体。

df[Reduce("&", lapply(df[c("col.x", "col.y")], "%in%", ValsToRetain)),] 
    col.x col.y  val 
6  A  H -1.6866933 
7  F  F 0.8377870 
11  J  J 0.4264642 
14  F  H 0.8781335 
19  D  D -0.3059627 

如果您有比较多列,那么你可以使用grep代替c("col.x", "col.y")选择他们喜欢grep("^col", names(df))