我正在尝试使用具有不同组的数据框,并查找哪些组共享公共值或设置值。
例如,假设我有一些不同水果的水果篮,我想知道哪些篮子里面有特定的水果。
这是我的水果篮:
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")
答案 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
。