Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 需要帮助优化类似cumsum的代码-sqldf、data.table、非equi联接_R_Dplyr_Data.table_Cumsum - Fatal编程技术网

R 需要帮助优化类似cumsum的代码-sqldf、data.table、非equi联接

R 需要帮助优化类似cumsum的代码-sqldf、data.table、非equi联接,r,dplyr,data.table,cumsum,R,Dplyr,Data.table,Cumsum,正在寻找帮助以优化我的sqldf代码,该代码基于非相等联接生成聚合的历史统计数据,即数据仅聚合到当前数据行 重要的是,任何解决方案都能够适用于许多不同的组,如按tourney_名称筛选聚合等。。在sqldf示例中 获取数据: library(dplyr); library(sqldf); data_list <- list() for(i in 2000:2018){ data_list[[i]] <- readr::read_csv(paste0('ht

正在寻找帮助以优化我的sqldf代码,该代码基于非相等联接生成聚合的历史统计数据,即数据仅聚合到当前数据行

重要的是,任何解决方案都能够适用于许多不同的组,如按tourney_名称筛选聚合等。。在sqldf示例中

获取数据:

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)

库(dplyr);图书馆(sqldf);data_listOP要求优化大量级联
sqldf
语句(在OP编辑之前)。不幸的是,OP没有口头解释他实现了哪些聚合。因此,需要大量的逆向工程

无论如何,下面是我将使用
data.table
实现相同结果的方法。OP的
sqldf
代码的执行时间从16秒减少到
数据.table
版本的不到0.2秒

data.table
已编辑示例的版本 OP编辑了该问题,以减少
sqldf
语句的数量。现在,只计算一个聚合

data2
中的新列
winner\u total\u wins
是在实际锦标赛开始之前,获胜者赢得的所有比赛的计数。此号码附在获胜者赢得的实际锦标赛的所有比赛上。(请注意,这与实际比赛之前赢得的比赛计数不同)

自1.9.8版(2016年11月25日)以来,
data.table
能够进行非等联接。此外,
fread()
建议只读取所选列,这将进一步加快I/O速度

library(data.table)  # v1.11.2

urls <- sprintf(
  "https://raw.githubusercontent.com/JeffSackmann/tennis_atp/master/atp_matches_%i.csv", 
  2000:2018)
selected_cols <- c("tourney_name", "tourney_date", "match_num", 
                   "winner_id", "winner_name", 
                   "loser_id", "loser_name") 

# read only selected columns from files & combine into one data object
matches <- rbindlist(lapply(urls, fread, select = selected_cols))

# non-equi join to compute aggregate, second join to append, order result 
system.time({
  result_nej <- matches[
    unique(matches[matches, on = .(winner_id, tourney_date < tourney_date), 
                   .(winner_overall_wins = .N), by = .EACHI]),
    on = .(winner_id, tourney_date)][
      order(-tourney_date, tourney_name, -match_num)]
})
使用
cumsum()
shift()
还有一种更快的替代解决方案:

system.time({
#累积操作需要有序的数据
设置顺序(比赛、锦标赛日期、锦标赛名称、比赛编号)
#添加锦标赛id以方便和简洁
比赛[,t\U id:=rleid(锦标赛日期,锦标赛名称)]
#按球员和锦标赛汇总

p_t_histOP要求优化大量级联
sqldf
语句(在OP编辑之前)。不幸的是,OP没有口头解释他实现了哪些聚合。因此,需要大量的反向工程

无论如何,我将使用
data.table
实现相同的结果。OP的
sqldf
代码的执行时间从16秒减少到
data.table
版本的不到0.2秒

data.table
已编辑示例的版本 OP编辑了这个问题,以减少
sqldf
语句的数量。现在,只计算一个聚合

data2
中的新列
winner\u total\u wins
是在实际锦标赛开始之前,赢家赢得的所有比赛的计数。此数字附加到赢家赢得的实际锦标赛的所有比赛。(请注意,这与实际比赛之前赢得的比赛计数不同)

自1.9.8版(2016年11月25日)以来,
数据表
能够进行非等联接。此外,
fread()
可以建议只读取所选列,从而进一步加快I/O速度

library(data.table)  # v1.11.2

urls <- sprintf(
  "https://raw.githubusercontent.com/JeffSackmann/tennis_atp/master/atp_matches_%i.csv", 
  2000:2018)
selected_cols <- c("tourney_name", "tourney_date", "match_num", 
                   "winner_id", "winner_name", 
                   "loser_id", "loser_name") 

# read only selected columns from files & combine into one data object
matches <- rbindlist(lapply(urls, fread, select = selected_cols))

# non-equi join to compute aggregate, second join to append, order result 
system.time({
  result_nej <- matches[
    unique(matches[matches, on = .(winner_id, tourney_date < tourney_date), 
                   .(winner_overall_wins = .N), by = .EACHI]),
    on = .(winner_id, tourney_date)][
      order(-tourney_date, tourney_name, -match_num)]
})
使用
cumsum()
shift()
还有一种更快的替代解决方案:

system.time({
#累积操作需要有序的数据
设置顺序(比赛、锦标赛日期、锦标赛名称、比赛编号)
#添加锦标赛id以方便和简洁
比赛[,t\U id:=rleid(锦标赛日期,锦标赛名称)]
#按球员和锦标赛汇总

p_t___________________________________________________________________用最少的列和行来演示您正在尝试做的事情。我猜您想要的是类似于
a[b,on=(p1_id,tourney_date>tourney_date)的东西,…]
,但我不想实际运行所有要检查的代码,抱歉。请务必在上查看此指南。感谢您的帮助…我在1 swoop中尝试了连接和聚合,但没有成功。您建议先进行连接,然后再进行聚合吗?
data3a[data3b,list(p1_总体_wins2=sum(p1_赢得),p1_totall_losses2=sum(p1_won==0),p1_totall_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]
也非常关注使我的示例具有可复制性,并希望检查一个大型数据集,因此是一个很长的示例。我将尝试将其归结为更基本的概念,看看是否能够理解,然后问一个更简单的问题。谢谢!这个问题太长了(对我来说).一般来说,如果你的问题比一页长,你要求的太多了。将你的问题简化为其核心内容。只是想展示我所有的尝试…我将尝试简化。让我知道现在是否更好。这是一个开始。如果你有一个小(!)用最少的列和行来演示您正在尝试做的事情。我猜您想要的是类似于
a[b,on=(p1_id,tourney_date>tourney_date)的东西,…]
,但我不想实际运行所有要检查的代码,抱歉。请务必在上查看此指南。感谢您的帮助…我在1 swoop中尝试了加入和聚合,但没有效果。那么,您是否建议进行加入
                     tourney_name tourney_date match_num winner_id   winner_name loser_id         loser_name winner_overall_wins
   1:             Australian Open     20180115       701    103819 Roger Federer   105227        Marin Cilic                1128
   2:             Australian Open     20180115       602    103819 Roger Federer   111202        Hyeon Chung                1128
   3:             Australian Open     20180115       504    103819 Roger Federer   104607      Tomas Berdych                1128
   4:             Australian Open     20180115       408    103819 Roger Federer   105916   Marton Fucsovics                1128
   5:             Australian Open     20180115       316    103819 Roger Federer   104755    Richard Gasquet                1128
  ---                                                                                                                           
1131:                   Marseille     20000207         3    103819 Roger Federer   102179      Antony Dupuis                   4
1132: Davis Cup WG R1: SUI vs AUS     20000204         2    103819 Roger Federer   102882 Mark Philippoussis                   3
1133:             Australian Open     20000117        90    103819 Roger Federer   102466        Jan Kroslak                   1
1134:             Australian Open     20000117        52    103819 Roger Federer   102021      Michael Chang                   1
1135:                    Adelaide     20000103         2    103819 Roger Federer   102533   Jens Knippschild                   0
system.time({
  # cumumlative operations require ordered data
  setorder(matches, tourney_date, tourney_name, match_num)
  # add tourney id for convenience and conciseness
  matches[, t_id := rleid(tourney_date, tourney_name)]
  # aggregate by player and tourney
  p_t_hist <- matches[, .(winner_won = .N), by = .(winner_id, t_id)]
  # compute cumulative sum for each player and 
  # lag to show only matches of previous tourneys
  tmp <- p_t_hist[order(t_id), 
                  .(t_id, winner_overall_wins = shift(cumsum(winner_won))), 
                  by = winner_id]
  # append new column & order result
  result_css <- matches[tmp, on = .(t_id, winner_id)][order(-t_id)]
})
p_name <- "Federer"; result_css[winner_name %like% p_name | loser_id %like% p_name]