我想选择所有包含至少一个我感兴趣的元素的分组。我能够通过创建一个中间数组来实现这一点,但我正在寻找更简单,更快速的东西。这是因为我的实际数据集有超过1M行(和20列),所以我不确定我是否有足够的内存来创建一个中间数组。更重要的是,我原始文件中的以下方法需要花费很多时间。
这是我的代码和数据:
a)数据
dput(Data_File)
structure(list(Group_ID = c(123, 123, 123, 123, 234, 345, 444,
444), Product_Name = c("ABCD", "EFGH", "XYZ1", "Z123", "ABCD",
"EFGH", "ABCD", "ABCD"), Qty = c(2, 3, 4, 5, 6, 7, 8, 9)), .Names = c("Group_ID",
"Product_Name", "Qty"), row.names = c(NA, 8L), class = "data.frame")
b)代码:我想选择至少有Group_ID
Product_Name = ABCD
#Find out transactions
Data_T <- Data_File %>%
group_by(Group_ID) %>%
dplyr::filter(Product_Name == "ABCD") %>%
select(Group_ID) %>%
distinct()
#Now filter them
Filtered_T <- Data_File %>%
group_by(Group_ID) %>%
dplyr::filter(Group_ID %in% Data_T$Group_ID)
c)预期输出
Group_ID Product_Name Qty
<dbl> <chr> <dbl>
123 ABCD 2
123 EFGH 3
123 XYZ1 4
123 Z123 5
234 ABCD 6
444 ABCD 8
444 ABCD 9
我现在已经挣扎了3个多小时。我通过SO Select rows with at least two conditions from all conditions查看了自动建议的帖子,但我的问题非常不同。
答案 0 :(得分:3)
我会这样做:
Data_File %>% group_by(Group_ID) %>%
filter(any(Product_Name %in% "ABCD"))
# Source: local data frame [7 x 3]
# Groups: Group_ID [3]
#
# Group_ID Product_Name Qty
# <dbl> <chr> <dbl>
# 1 123 ABCD 2
# 2 123 EFGH 3
# 3 123 XYZ1 4
# 4 123 Z123 5
# 5 234 ABCD 6
# 6 444 ABCD 8
# 7 444 ABCD 9
说明:如果有任何符合条件的行(在组内),any()
将返回TRUE
。然后将长度为1的结果再循环到组的整个长度,并保留整个组。您也可以使用sum(Product_name %in% "ABCD") > 0
作为条件,但任何读取非常好。如果您想要更复杂的条件,请使用sum
,例如3个或更多匹配的产品名称。
我更喜欢%in%
到==
这样的事情,因为它有NA
更好的行为,如果你想按组检查多个产品中的任何一个,它很容易扩展。
如果速度和效率是个问题,data.table
会更快。我会这样做,它依赖于键控连接进行过滤并且不使用非data.table操作,所以它应该非常快:
library(data.table)
df = as.data.table(df)
setkey(df)
groups = unique(subset(df, Product_Name %in% "ABCD", Group_ID))
df[groups, nomatch = 0]
# Group_ID Product_Name Qty
# 1: 123 ABCD 2
# 2: 123 EFGH 3
# 3: 123 XYZ1 4
# 4: 123 Z123 5
# 5: 234 ABCD 6
# 6: 444 ABCD 8
# 7: 444 ABCD 9