【问题标题】:R data.table if then sumif lookup using joinR data.table 如果然后 sumif 使用连接查找
【发布时间】:2019-09-07 10:25:42
【问题描述】:

我希望在 events_table 中查找 individual id 并将 total_duration 计算为 date 之前所有事件的持续时间的总和。

持续时间是date_startdate (table1) 之间的时间,除非事件结束(即有date_end),在这种情况下如果date_end < dateduration = date_end - date_start

在伪代码中:

IF (date>date_start) Then{
   IF(date_end < date & date_end != NA) Then{
       duration = date_end-date_start
   } else if (date_start < date) {
       duration = date - date_start
   }
}
Then sum all the durations separately for each "individual_id" and "date" combo

我正在使用 data.tables,因为我有大表(>1m 行)。

我的数据看起来有点像这样:

 table1 <- fread(
      "individual id | date       
       1             |  2019-01-02
       1             |  2019-01-03
       2             |  2019-01-02
       2             |  2019-01-03", 
      sep ="|"
    )
    events_table<- fread(
      "individual id | date_start  | date_end
       1             |  2018-01-02 |   NA     
       1             |  2018-01-04 | 2018-07-01     
       1             |  2018-01-05 |   NA       
       2             |  2018-01-01 |   NA         
       2             |  2018-01-02 |   NA           
       2             |  2018-01-05 | 2018-11-21",
      sep = "|"
    )

输出应该如下:

 table1 <- fread(
          "individual id | date         | total_duration
           1             |  2019-01-02  |    905
           1             |  2019-01-03  |    907
           2             |  2019-01-02  |    1051
           2             |  2019-01-03  |    1053", 
          sep ="|"
        )

我在开始查询时的最佳猜测来自:

table1[, total_duration:= events_table[table1, 
                              on = .(`individual id`, date>date_start), 
                              sum(date-date_start),
                              by = .EACHI][["V1"]]]

但我不知道包含 if 条件的语法。

感谢您的帮助。

【问题讨论】:

  • 我想你错过了第二个 fread 中的"
  • @akrun 你是对的,我已经更新了它

标签: r data.table rmysql


【解决方案1】:
# formatting
table1[, date := as.IDate(date)]
events_table[, `:=`(date_start = as.IDate(date_start), date_end = as.IDate(date_end))]

# list max dur
events_table[, dur := date_end - date_start]

# add up completed events
table1[, v1 := 
  events_table[.SD, on=.(`individual id`, date_end <= date), sum(x.dur, na.rm = TRUE), by=.EACHI]$V1
]

# add on incomplete events
table1[, v2 := 
  events_table[!is.na(date_end)][.SD, on=.(`individual id`, date_start <= date, date_end > date), sum(i.date - x.date_start, na.rm = TRUE), by=.EACHI]$V1
]

# add on ill-defined events
table1[, v3 := 
  events_table[is.na(date_end)][.SD, on=.(`individual id`, date_start <= date), sum(i.date - x.date_start, na.rm = TRUE), by=.EACHI]$V1
]

table1[, v := v1 + v2 + v3]

   individual id       date total_duration  v1 v2  v3    v
1:             1 2019-01-02            905 178  0 727  905
2:             1 2019-01-03            907 178  0 729  907
3:             2 2019-01-02           1051 320  0 731 1051
4:             2 2019-01-03           1053 320  0 733 1053

您不必定义三个不同的列,尽管它更易于调试。相反,您可以初始化 table1[, v := 0] 并为每个步骤执行 table1[, v := v + ...]

【讨论】:

  • 它看起来正是我所希望的,我明天会测试它,非常感谢@frank
  • 我收到错误消息,即为不完整事件 (v2) 生成持续时间的命令导致行数过多。 Join results in 19190493 rows; more than 1027748 = nrow(x)+nrow(i). Check for duplicate key values in i each of which join to the same group in x over and over again. 因为我们正在添加一个附加条件 (date_end &gt; date),它不应该导致更少的行吗?
  • 是不是因为我们要参加两次约会? @弗兰克
  • @Laurence_jj 您可以添加参数allow.cartesian=TRUE 来强制计算;见?data.table。发生这种情况是因为 i = table1 的某些行根据那些 on= 条件与 x = events_table[!is.na(date_end)] 的许多行匹配。如果 v2 给出错误而 v3 没有给出错误,我会感到困惑,因为正如你所说,v2 使用更窄的 on= 条件......
  • 我尝试使用 allow.cartesian=TRUE 并且它运行了,但是 v2 只给了我零,其中数据显然应该导致 date-date_start 给出更多的零。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-09
  • 1970-01-01
  • 2015-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
相关资源
最近更新 更多