Могу ли я сделать это с data.table без использования функции merge ()? - PullRequest
2 голосов
/ 29 мая 2019

Я работаю с очень большими наборами данных и пытаюсь ускорить мой R-код. Вот пример данных:

dt <- data.table(id = c(100,101,102,103, 104), sex = c("m","f","m","m","f"), 
value = c(32,14,32,03,03))

data look like this :
    id sex value
1: 100   m    32
2: 101   f    14
3: 102   m    32
4: 103   m     3
5: 104   f     3 

Окончательный вывод, который я хочу:

   value f.value m.value f   m
1:     3    1       1    1   1
2:    14    1       NA   1   NA
3:    32    NA      2    NA  2

Код, который я сейчас использую:

dt_u <- unique(dt, by = c("id", "sex", "value"))
dt_u <- dt_u[, .(n = .N), keyby = .(value, sex)]
dt_u <- dcast(dt_u, value ~ sex, value.var = "n")
dt_t <- dt[, .(n = .N), keyby = .(value, sex)]
dt_t <- dcast(dt_t, value ~ sex, value.var = "n")
dt <- merge(dt_t, dt_u, by = "value", all = TRUE)

Код работает отлично, проблема в том, что объединение dt_u и dt_t может занять много времени на 10GB + данных. Итак, мой вопрос: Возможно ли получить тот же конечный результат без необходимости "разбивать" данные и затем объединять их?

Также я бы хотел, чтобы ответ был в data.table, если это возможно, спасибо.

РЕДАКТИРОВАТЬ: пример и объяснение. Идентификатор представляет человека, этот человек может посещать одно и то же местоположение (значение) более одного раза. В этом примере вы можете сказать, что каждое значение представляет отдельный город.

IE:

dt <- data.table(value = c(21,21,21,21,21,40,1,22,1,1,22, 22, 49, 
49,21,21,1,1,1), id = 
c(1000716624,1000722724,1000716624,1000746824,1001012024,
1002067324,1002743624,1002743645, 1002743636, 
1002743423,1000716624,1000722724, 1000722724,1001012024, 
1000716624,1000716624,1002743624,1002743624,1002743624), sex = c("f", "m", 
"m", "m", "f", "f", "m", "f", "f", "m", "f", "m", "m", "f","f","f", "m", 
"m", "m"))

Выход:

 value   places_women   places_men  number_women   number_men
1:     1            1          5            1          2
2:    21            4          3            2          3
3:    22            2          1            2          1
4:    40            1         NA            1         NA
5:    49            1          1            1          1

Ответы [ 2 ]

3 голосов
/ 29 мая 2019

Это работает для второго примера (на основе обратного инжиниринга желаемого результата):

> dcast(dt, value ~ sex, value.var=list("value", "id"), fun=list(length, uniqueN), fill=NA)
   value value.1_length_f value.1_length_m id_uniqueN_f id_uniqueN_m
1:     1                1                5            1            2
2:    21                4                3            2            3
3:    22                2                1            2            1
4:    40                1               NA            1           NA
5:    49                1                1            1            1

Более точное описание того, какие вычисления должны быть в каждом столбце (и, возможно, более естественные имена столбцов в примере), поможет, если это не сработает для полной проблемы.

1 голос
/ 29 мая 2019
library(data.table)

dt <- data.table(id = c(100,101,102,103, 104), sex = c("m","f","m","m","f"), 
                 value = c(32,14,32,03,03))

dcast(unique(unique(dt, 
                    by = c("id", "sex", "value"))[ , 

            count := .N, by = list(value,sex)][,
        id:=NULL]), 
value ~ sex, value.var = "count")

#>    value  f  m
#> 1:     3  1  1
#> 2:    14  1 NA
#> 3:    32 NA  2

Создано в 2019-05-29 пакетом Представления (v0.3.0)

...