【发布时间】:2021-03-20 22:53:59
【问题描述】:
我有两个数据集,想要进行 inner join 然后 group 但由于我的数据有 >1 亿行,inner join 是 笛卡尔合并 进一步增加了最终数据集。我想了解如何以一种高效、快捷的方式来做到这一点。我当前的合并代码运行了很长时间。
示例数据集(此示例没有笛卡尔数据,但我的原始数据集有)
library("data.table")
library("sqldf")
library("purrr")
orders <- data.table(date = as.POSIXct(c('2012-08-28','2012-08-29','2012-09-01', '2012-08-30')),
first_name = as.character(c('John','George','Henry', 'Markel')),
last_name = as.character(c('Doe','Smith','Smith', 'Markel')),
qty = c(10,50,6, 0))
dates <- data.table(date = seq(from = as.POSIXct('2012-08-28'),
to = as.POSIXct('2012-09-07'), by = 'day'),
week = seq(from = 1, to = 11, by = 1))
我拥有的等效 sqldf 代码:这要慢得多
final_data <- sqldf("select first_name,
last_name,
week,
sum(qty) as total_qty
from orders a inner join dates b
on a.date = b.date
where a.first_name = a.last_name
group by first_name,
last_name,
week
having sum(qty) = 0;")
等效的 data.table 代码(必须匹配 sqldf 输出)
final_data_2 <- merge(
x = orders[ first_name == last_name,]
, y = dates
, all = FALSE
, allow.cartesian = TRUE) %>%
.[, total_qty := sum(qty), by = .(first_name, last_name, week) ] %>%
.[total_qty == 0, .(first_name, last_name, week, total_qty)]
@manoftheshark 的备用代码
orders[dates, on = 'date', allow.cartesian = TRUE][, total_qty := sum(qty), by = .(first_name, last_name, week)][total_qty == 0, .(first_name, last_name, week, total_qty)]
【问题讨论】:
-
您确定这是笛卡尔合并吗?样本数据似乎没有显示这一点。还不清楚应该如何处理
week,因为它不是聚合函数的一部分,也不是分组依据。 -
是的,我的原始数据是笛卡尔合并,这只是一个例子。
week是选择的一部分。希望我在这里有意义 -
如果有
2012-09-06, Markel, Markel, 0这样的记录怎么办?first_name和last_name被分组,qty被求和,但是week是如何处理的呢?它会成为一个独特的记录吗?还是应该返回一条记录? -
@manotheshark 感谢您指出这一点。我已将星期添加到分组依据
-
在 SO 上发布问题时,我建议删除
%>%和.以使其更易于阅读,并通过减少额外的依赖项使其更易于重现。数据处理管道可以通过链接[操作符来表示。
标签: r postgresql data.table sqldf