dplyr:在进行范围过滤时添加限定列名称("filter_all",...)
dplyr: adding qualifying column names while doing scoped filtering ("filter_all", ...)
我有一个非常宽和长的数据集,我需要从中挑选出任何选择的变量满足特定条件的行。到目前为止,dplyr
和 any_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),我想多次显示该行——在本例中都使用 v1
和 v2
.
试试这个代码:
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
我有一个非常宽和长的数据集,我需要从中挑选出任何选择的变量满足特定条件的行。到目前为止,dplyr
和 any_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),我想多次显示该行——在本例中都使用 v1
和 v2
.
试试这个代码:
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