R data.table 平均值如果使用连接查找

R data.table average if lookup using join

我只想做一个简单的平均 if(就像 excel 中的命令 average if)。我正在使用 data.tables 来提高效率,因为我有相当大的表(~100 万行)。

我的目标是查找

Table 1 
| individual id | date        |
-------------------------------
| 1             |  2018-01-02 |
| 1             |  2018-01-03 |
| 2             |  2018-01-02 |
| 2             |  2018-01-03 |

Table 2 
| individual id | date2       | alpha |
---------------------------------------
| 1             |  2018-01-02 |  1    |  
| 1             |  2018-01-04 |  1.5  |
| 1             |  2018-01-05 |  1    |
| 2             |  2018-01-01 |  2    |  
| 2             |  2018-01-02 |  1    |
| 2             |  2018-01-05 |  4    |

目标结果

Updated table 1
| individual id | date        | mean(alpha) |
---------------------------------------------
| 1             |  2018-01-02 |  1          |
| 1             |  2018-01-03 |  1          |
| 2             |  2018-01-02 | 1.5         |
| 2             |  2018-01-03 | 1.5         |

这只是表 2 中此人的所有值的平均值,该值发生在(日期 2)之前(包括)该日期。 结果可以通过以下 mysql 命令生成,但我无法在 R 中重现它。

update table1
            set daily_alpha_avg = 
      (select avg(case when date2<date then alpha else 0 end) 
      from table2
      where table2.individual_id= table1.individual_id
      group by individual_id);

到目前为止我最好的猜测是:

table1[table2, on = .(individual_id, date>=date2), 
          .(x.individual_id, x.date, bb = mean(alpha)), by= .(x.date, x.individual_id)]

table1[, daily_alpha_avg := table2[table1, mean(alpha), on =.(individual_id, date>=date2)]]

但这行不通,我知道这是错误的,我只是不知道如何解决它。

感谢您的帮助

使用 by = .EACHI 您可以执行以下操作:

table2[table1, 
       on = .(`individual id`), 
       .(date = i.date, mean_alpha = mean(alpha[date2 <= i.date])),
       by = .EACHI]

#    individual id       date mean_alpha
# 1:             1 2018-01-02        1.0
# 2:             1 2018-01-03        1.0
# 3:             2 2018-01-02        1.5
# 4:             2 2018-01-03        1.5

编辑:

# Assign by reference as a new column
table1[, mean_alpha := table2[table1, 
                              on = .(`individual id`), 
                              mean(alpha[date2 <= i.date]),
                              by = .EACHI][["V1"]]]

编辑 2:

下面是 Frank 在评论区推荐的稍微优雅一点的方法。

# In this solution our date columns can't be type character
table1[, date := as.Date(date)]
table2[, date2 := as.Date(date2)]

table1[, mean_alpha := table2[table1, # or equivalently .SD instead of table1
                              on = .(`individual id`, date2 <= date), 
                              mean(alpha), 
                              by = .EACHI][["V1"]]]

可重现数据

table1 <- fread(
  "individual id | date       
   1             |  2018-01-02
   1             |  2018-01-03
   2             |  2018-01-02
   2             |  2018-01-03", 
  sep ="|"
)
table2 <- fread(
  "individual id | date2       | alpha
   1             |  2018-01-02 |  1     
   1             |  2018-01-04 |  1.5 
   1             |  2018-01-05 |  1   
   2             |  2018-01-01 |  2     
   2             |  2018-01-02 |  1   
   2             |  2018-01-05 |  4",
  sep = "|"
)

tidyverse 的性能对您来说还不够吗?

我无法用 date2 < date 复制你的 table 所以我添加了 =.

#Please provide 

table1 <- tribble(~individual_id,~date,
                  1,"2018-01-02",
                  1,"2018-01-03",
                  2,"2018-01-02",
                  2,"2018-01-03")

table2 <- tribble(~individual_id,~date2,~alpha,
                  1,"2018-01-02",1,
                  1,"2018-01-04",1.5,
                  1,"2018-01-05",1,
                  2,"2018-01-01",2,
                  2,"2018-01-02",1,
                  2,"2018-01-05",4)

df <- left_join(table1,table2) %>%
  mutate(date = as.Date(date),
         date2 = as.Date(date2))

df %>% 
  group_by(individual_id,date) %>% 
  mutate(case = ifelse(date2<=date,alpha,NA)) %>% 
  summarise(mean_alpha = mean(case,na.rm = TRUE))

您也可以选择使用 tidyverse 生成 sql 查询,还有 sql_translations,查看 https://dbplyr.tidyverse.org/articles/sql-translation.html 并使用 show_query 函数确保您在 sql 和 R

之间使用相同的逻辑

只需使用 sqldf 包,并将您的查询放入 sqldf().

library(sqldf)
sqldf("your SQL goes here")
table1

就是这样