dplyr:在进行范围过滤时添加限定列名称("filter_all",...)

dplyr: adding qualifying column names while doing scoped filtering ("filter_all", ...)

我有一个非常宽和长的数据集,我需要从中挑选出任何选择的变量满足特定条件的行。到目前为止,dplyrany_vars 中的范围过滤非常接近我的需要。举例说明:

x <- tibble(v1 = c(1, 1, 5, 3, 4), v2 = c(3, 1, 2, 1, 2))
filter_all(x, any_vars( . == min(.)))

产生

# A tibble: 3 x 2
     v1    v2
  <dbl> <dbl>
1     1   3
2     1   1
3     3   1

我想将 "filtering variable" 的名称添加到结果行中,如下所示:

     v1    v2   var
  <dbl> <dbl> <chr>
1     1   3    v1
2     1   1    v1
3     1   1    v2
4     3   1    v2

有什么建议吗?我怀疑 purrr 中的 map 函数之一可能会一个一个地进行过滤,然后再合并结果。

当一个变量符合多个变量的条件时(感谢@Moody_Mudskipper),我想多次显示该行——在本例中都使用 v1v2 .

试试这个代码:

  x%>%filter_all(., any_vars( . == min(.)))%>%
 data.frame(.,var=apply(.,1,function(i) names(.)[i==sapply(x,min)]))

如果这对您有帮助,请告诉我们。谢谢。

此代码在一种情况下会失败:如果一行中有多个变量是最小值。例如在发布的示例中,如果有一行都为 1,则此代码将失败。谢谢

好了,这应该适用于广泛的数据集。

x <- tibble(v1 = c(1, 1, 5, 3, 4), v2 = c(3, 1, 2, 1, 2))

library(dplyr)
library(tidyr)
x %>%
  mutate_all(rank,ties.method ="min") %>%
  gather(var,val) %>%
  cbind(x,.) %>%
  filter(val ==1) %>%
  select(-val)

#   v1 v2 var
# 1  1  3  v1
# 2  1  1  v1
# 3  1  1  v2
# 4  3  1  v2

避免建立大温度table:

gathered <- x %>%
  mutate_all(rank,ties.method ="min") %>%
  gather(var,val)
rows_to_keep <- which(gathered$val == 1)
cbind(x[(rows_to_keep-1) %% nrow(x) + 1,],gathered[rows_to_keep,])

这更丑陋,但我认为这是我能想到的最有效的方法:

log_df       <- mutate_all(x,function(x){x==min(x)}) # identify rows that contain min (no time wasted sorting here)
filter1      <- rowSums(log_df)>0  # to get rid of uninteresting rows
x2           <- x[filter1,]
log_df2      <- log_df[filter1,]
gathered     <- gather(log_df2,var,val) # put in long format
rows_to_keep <- which(gathered$val)
cbind(x2[(rows_to_keep-1) %% nrow(x2) + 1,],gathered[rows_to_keep,]) %>% select(-val)

感谢创建新列的想法,我下面的解决方案在过滤之前首先存储变量名称。让我知道您是否可以对此进行改进:

x %>%  
  mutate_all(funs(qual = . == min(.))) %>%
  filter_at(vars(ends_with("_qual")), any_vars(. == TRUE)) %>%
  gather(var, qual, ends_with("_qual")) %>%
  filter(qual==TRUE) %>%
  select(-qual) %>%
  extract(var, "var")

第一步后的中间table:

     v1    v2 v1_qual v2_qual
1     1     3    TRUE   FALSE
2     1     1    TRUE    TRUE
3     5     2   FALSE   FALSE
4     3     1   FALSE    TRUE
5     4     2   FALSE   FALSE