如何将dplyr与参数向量一起使用

时间:2015-09-25 01:45:33

标签: r dplyr

我正在尝试使用具有不同组的数据框,并查找哪些组共享公共值或设置值。

例如,假设我有一些不同水果的水果篮,我想知道哪些篮子里面有特定的水果。

这是我的水果篮:

fruit_baskets <- data.frame(basket=c(rep("blue",3),rep("red",3),rep("green",3)),
                        fruits=c("orange", "tomato", "pear", 
                                 "orange", "tomato", "grape",
                                 "strawberry", "tomato", "grape"))
# > print(fruit_baskets)
#   basket     fruits
# 1   blue     orange
# 2   blue     tomato
# 3   blue       pear
# 4    red     orange
# 5    red     tomato
# 6    red      grape
# 7  green strawberry
# 8  green     tomato
# 9  green      grape

以及我找到哪些篮子包含特定水果的功能:

find_similar_baskets_1 <- function(some_baskets, fruit) {
  some_baskets %>% 
    group_by(basket) %>% 
    summarise(xxx_1=max(ifelse(fruits==fruit, 1, 0))) %>% 
    filter(xxx_1 == 1) %>% 
    .[[1]] %>% unique %>% as.character
}

我可以使用此功能查找带番茄的篮子。

> find_similar_baskets_1(fruit_baskets, "tomato")
[1] "blue"  "green" "red" 

同样,我可以创建一个函数来查找哪些篮子都有两个水果。

find_similar_baskets_2 <- function(some_baskets, fruit_1, fruit_2) {
  some_baskets %>% 
  group_by(basket) %>% 
  summarise(xxx_1=max(ifelse(fruits==fruit_1, 1, 0)),
            xxx_2=max(ifelse(fruits==fruit_2, 1, 0))) %>% 
  filter(xxx_1 == 1 & xxx_2 == 1) %>% 
  .[[1]] %>% unique %>% as.character
}

现在我可以用这个功能找到哪个篮子里有一个橙子和一个西红柿(蓝色和红色)以及哪个篮子有番茄和葡萄(绿色和红色)。

find_similar_baskets_2(fruit_baskets, "orange", "tomato")
#[1] "blue" "red" 

find_similar_baskets_2(fruit_baskets, "tomato", "grape")
#[1] "green" "red" 

在理想世界中,我能够创建一个不依赖于我给它的值(即水果)数量的单个函数。

find_similar_groups <- function(df, group_column, value_column, value_vector)

我可以有一个任意大的值向量,其中group列(在本例中为“basket”)和value列(“fruits”)不在函数中。

df = fruit_baskets
column = "fruits"
values = c("tomato")  or c("orange", "tomato")

2 个答案:

答案 0 :(得分:3)

这是另一种方式:

select_baskets_having_fruit <- function(bs,...){
    fs <- c(...)
    bs %>% 
        select_(basket, fruits) %>%
        group_by(basket) %>%
        filter(all(fs %in% fruits)) %>%
        .$basket %>% unique %>% as.character
}

还有一些例子:

fruit_baskets %>% select_baskets_having_fruit('tomato') 
# "blue"  "red"   "green"

fruit_baskets %>% select_baskets_having_fruit('orange','tomato') 
# "blue" "red"

fruit_baskets %>% select_baskets_having_fruit('tomato','grape') 
# "red"   "green"

泛化将此应用于其他分组并选择变量......

select_grp_with_x <- function(dat,...,g="basket",x="fruits"){
    xs <- c(...)
    dat %>% 
        select_(g,x) %>%
        group_by_(g) %>%
        filter(all(xs %in% .[[x]])) %>%
        .[[g]] %>% unique %>% as.character
}

fruit_baskets %>% select_grp_with_x('orange','tomato')
在我看来,

dplyr不太适合制作广义函数,因为你必须使用像.[[]]这样的结构和下划线函数,比如select_

我更喜欢,例如

library(magrittr)
select_grp_with_x2 <- function(dat,...,g,x)
    split(dat[[x]], dat[[g]]) %>% 
        sapply( function(z) all(c(...) %in% z) ) %>% 
        which %>% names

select_grp_with_x2(fruit_baskets,'orange','tomato',g='basket',x='fruits') # "blue" "red"

在了解基础R的情况下,我认为这比dplyr方法更容易阅读。但是,如果你正在设计一个效率函数(快速运行而不吃内存),你可能想要使用一种完全不同的方法。

答案 1 :(得分:2)

这是一个答案,它以水果列表作为输入:

library(dplyr)
findbaskets <- function(df, fruitlist){
  x <- df %>% group_by(basket) %>%
              summarise(subset = all(fruitlist %in% fruits))
  x$basket[x$subset]
}
findbaskets(fruit_baskets, list("orange", "grape"))
[1] red

如果您想查看它是否包含all列出的水果,请使用上面的内容,如果您需要,请将all更改为any