【发布时间】:2018-05-03 21:14:43
【问题描述】:
寻求帮助以优化我的 sqldf 代码,该代码基于非 equi 连接生成汇总的历史统计信息,即数据只能汇总到当前数据行。
重要的是,任何解决方案都能够适用于许多不同的组,例如在 sqldf 示例中按 tourney_name 过滤聚合等。
获取数据:
library(dplyr); library(sqldf); data_list <- list()
for(i in 2000:2018){
data_list[[i]] <-
readr::read_csv(paste0('https://raw.githubusercontent.com/JeffSackmann/tennis_atp/master/atp_matches_',i,'.csv')) %>%
as.data.frame}
data <- data.table::rbindlist(data_list)
data <- select(data, tourney_name, tourney_date, match_num, winner_id, winner_name, loser_id, loser_name)
system.time(
data2 <- sqldf("select a.*,
count(b.winner_id) as winner_overall_wins
from data a
left join data b
on (a.winner_id = b.winner_id and a.tourney_date > b.tourney_date)
group by a.tourney_name, a.tourney_date, a.match_num, a.winner_id
order by tourney_date desc, tourney_name, match_num desc",
stringsAsFactors = FALSE)
) # takes 16 sec, would like to look for a vectorized solution
head(data2)
我尝试加快代码速度的方法:
For 循环 - 太慢了
Dplyr 完全连接/过滤器 - 内存超过 60gb。
Data.table/cumsum - 无法让代码正常工作。更喜欢非 data.table 方法,但愿意学习通用解决方案
谢谢!
【问题讨论】:
-
这个问题太长了(对我来说)。一般来说,如果您的问题比一页长,那么您的要求就太多了。将您的问题简化为核心本质。
-
只是想展示我所有的尝试......我会尽量简化。让我知道现在是否更好。
-
这是一个开始。如果您有一个小的(!)玩具示例,而不是用最少的列和行来说明您正在尝试做什么,那就更好了。我的猜测是您想要类似于
a[b, on = .(p1_id, tourney_date > tourney_date), ...]的东西,但我不想实际运行您的所有代码来检查,抱歉。并在asking great questions 上查看本指南。 -
感谢您的帮助...我一口气尝试了加入和聚合,但没有成功。您是否建议先进行联接,然后再进行聚合?
data3a[data3b, list(p1_overall_wins2 = sum(p1_won), p1_overall_losses2 = sum(p1_won == 0), p1_overall_ace2 = mean(p1_ace, na.rm = TRUE)), by = list(tourney_name, tourney_date, match_num, p1_id), on = .(p1_id = p1_id2, tourney_date > tourney_date2), allow.cartesian = TRUE] -
还非常注重使我的示例可重现,并希望检查大型数据集,因此示例很长。我会试着把它归结为更基本的概念,看看我能不能弄清楚,然后问一个更简单的问题。谢谢!
标签: r dplyr data.table cumsum