我想选择至少包含我感兴趣的元素之一的所有分组。我可以通过创建中间数组来做到这一点,但我正在寻找更简单、更快的东西。这是因为我的实际数据集有超过 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")
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我现在已经为此苦苦挣扎了3个多小时。我查看了自动建议的线程 SO:从所有条件中选择至少有两个条件的行,但我的问题非常不同。
我会这样做:
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
Run Code Online (Sandbox Code Playgroud)
说明:如果有任何行(组内)符合条件,any()则返回。TRUE然后,长度为 1 的结果将被回收到组的完整长度,并且整个组将被保留。您也可以使用sum(Product_name %in% "ABCD") > 0as 条件来执行此操作,但 any 读起来非常好。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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1033 次 |
| 最近记录: |