【问题标题】:How to use dplyr with a vector of arguments如何将 dplyr 与参数向量一起使用
【发布时间】:2015-10-19 09:51:56
【问题描述】:

我正在尝试获取具有不同组的数据框,并找出哪些组共享一个共同值或 一组值。

例如,假设我有一些装有不同水果的水果篮,我想找出哪些篮子里有特定的水果。

这是我的水果篮:

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)

我可以有一个任意大的值向量,而组列(在本例中为“篮子”)和值列(“水果”)不在函数中。

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

【问题讨论】:

  • 关于max 或ifelse,您想使用any,例如fruit_baskets %&gt;% group_by(basket) %&gt;% filter(any(fruits=='tomato')) %&gt;% .$basket %&gt;% unique %&gt;% as.character

标签: r dplyr


【解决方案1】:

这是另一种方式:

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 方式更容易阅读。但是,如果您正在设计一个提高效率的函数(快速运行而不消耗内存),您可能希望使用完全不同的方法。

【讨论】:

  • 感谢 Frank 的回答以及使用 any 代替 max(ifelse()) 的建议。我还打算询问如何将“水果”和“篮子”指定为参数而不是函数中的变量(我更新了问题)。
  • @dhandler 我已经扩展到这种情况。如果您通过g 和x 作为basket 和fruit 的替代,它应该可以工作。我仍在编辑以添加更多评论。
【解决方案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。

【讨论】:

  • 你将如何修改它,以便“水果”和“篮子”变量不需要进入函数内部并且可以任意选择?
猜你喜欢
  • 2017-09-10
  • 2020-08-30
  • 2013-06-04
  • 2021-09-07
  • 2014-02-26
  • 2021-05-16
  • 2017-12-02
  • 2016-10-17
  • 2021-01-19
相关资源
最近更新 更多