【问题标题】:R data.table average if lookup using join如果使用连接查找,R data.table 平均值
【发布时间】:2019-04-17 16:20:03
【问题描述】:

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

我的目标是查找

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)]]

但这不起作用,我知道它错了我只是不知道如何解决它。

感谢您的帮助

【问题讨论】:

  • @sindri_baldur 你是对的,我已经更新了。非常感谢

标签: r data.table rmysql


【解决方案1】:

使用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

这是弗兰克在评论部分建议的稍微优雅的方式。

# 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 = "|"
)

【讨论】:

  • 你的答案正是我要找的!!唯一的问题是我得到了一个未映射到我的 table1 的新表。理想情况下,我希望在我的 table1 上创建一个带有结果的新列,如果没有可用数据,则为 na 或零。目前我在输出列中也只有 NA,但这可能是我的数据
  • @Laurence_jj 添加了将计算映射到新列的替代解决方案。如果不匹配,应该给你NA...
  • @Laurence_jj 这只是从 data.frame 中提取一列的基本 R 语法。 table2[table1, on = .("individual id"), mean(alpha[date2 &lt;= i.date]), by = .EACHI] 将返回 data.table 但我只想要那一列。
  • @Laurence_jj 你尝试了什么?使用 sum(date2 &lt;= i.date) 而不是 mean(alpha[date2 &lt;= i.date]) 我得到匹配的数量。
  • 如果您使用as.IDateas.Date 覆盖-转换日期,那么table1[, v := table2[.SD, on=.(`individual id`, date2 &lt;= date), mean(alpha), by=.EACHI]$V1] 也可以。顺便说一句,很好的答案:)
【解决方案2】:

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

我无法仅使用 date2

#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 之间使用相同的逻辑

【讨论】:

    【解决方案3】:

    只需使用 sqldf 包,然后将查询放入 sqldf()

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

    就是这样

    【讨论】:

    • 这个我试过了,但是很慢,跑了10m或者20m就放弃了
    • 然后使用 tidyverse 包
    猜你喜欢
    • 2019-09-07
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    相关资源
    最近更新 更多