Внутреннее объединение на лучших методах набора данных - PullRequest
0 голосов
/ 12 октября 2019

Я пытаюсь объединить два больших набора данных (около 3,5 м строк в каждом), используя dplyr::inner_join. Я работаю на мощной машине с 40+ ядрами. Я не уверен, что пользуюсь самой машиной, так как я все равно не распараллеливаю задачу. Как мне решить проблему, которая требует много времени для запуска?

Best

Ответы [ 2 ]

1 голос
/ 12 октября 2019

Я не думаю, что 3.5M внутреннее объединение будет иметь проблемы с производительностью, если только ваши два последних набора данных не будут 3.5M * 3.5M после объединения из-за дублирования ключевых столбцов в ваших наборах данных (дублированные значения объединенных столбцов)

Обычно в R нет функций, которые будут использовать несколько ядер. Для этого вам нужно разделить данные в пакетном режиме, которые можно обрабатывать отдельно, а затем объединить итоговые результаты и рассчитать их дальше. Вот псевдокод с использованием библиотеки dplyr & doParallel

library(dplyr)
library(doParallel)

# Parallel configuration #####
cpuCount <- 10
# Note that doParallel will replicated your environment to and process on multiple core
# so if your environment is 10GB memory & you use 10 core
# it would required 10GBx10=100GB RAM to process data parallel
registerDoParallel(cpuCount)

data_1 # 3.5M rows records with key column is id_1 & value column value_1
data_2 # 3.5M rows records with key columns are id_1 & id_2

# Goal is to calculate some stats/summary of value_1 for each combination of id_1 + id_2
id_1_unique <- unique(data_1$id_1)
batchStep <- 1000
batch_id_1 <- seq(1, length(id_1_unique )+batchStep , by=batchStep )

# Do the join for each batch id_1 & summary/calculation then return the final_data
# foreach will result a list, for this psuedo code it is a list of datasets
# which can be combined use bind_rows
summaryData <- bind_rows(foreach(index=1:(length(batch_id_1)-1)) %dopar% {
    batch_id_1_current <- id_1_unique[index:index+batchStep-1]
    batch_data_1 <- data_1 %>% filter(id_1 %in% batch_id_1_current)
    joined_data <- inner_join(batch_data_1, batch_data_2, by="id_1")
    final_data <- joined_data %>%
        group_by(id_1, id_2) %>%
        #calculation code here
        summary(calculated_value_1=sum(value_1)) %>%
        ungroup()
    return(final_data)
})


0 голосов
/ 12 октября 2019

Вам следует попробовать пакет data.table, который намного более эффективен , чем dplyr для больших наборов данных. Я скопировал код внутреннего соединения из здесь.

library(data.table)
DT <- data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), v=1:9)
X  <- data.table(x=c("c","b"), v=8:7, foo=c(4,2))
DT[X, on="x", nomatch=0] # inner join
                         # SELECT DT INNER JOIN X ON DT$x = X$x

Althought data.table не использует распараллеливание, это будет быстрее, чем inner_join и лучший вариант дляНасколько мне известно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...