R data.table среднее, если поиск с использованием соединения - PullRequest
0 голосов
/ 16 апреля 2019

Все, что я хочу сделать, - это просто среднее значение if (точно так же, как среднее значение команды, если в excel). Я работаю с data.tables для эффективности, так как у меня довольно большие таблицы (~ 1 м строк).

Моя цель - найти

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

но это не работает, я знаю, что это неправильно, я просто не знаю, как это исправить.

Спасибо за любую помощь

Ответы [ 3 ]

5 голосов
/ 16 апреля 2019

Используя 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

Edit:

# 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 = "|"
)
0 голосов
/ 16 апреля 2019

Просто используйте пакет sqldf и поместите ваш запрос в sqldf () .

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

Вот и все

0 голосов
/ 16 апреля 2019

Разве вам не хватает производительности 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

...