Dataframe слишком большой для суперкомпьютера

Я пытаюсь создать матрицу доноров и получателей, заполненную суммой пожертвований, произведенных в каждой паре, где хранятся возможные НС.

Он работает хорошо для небольших наборов данных (см. Пример с примерами ниже), но когда я переключаюсь на национальные наборы данных (3 м записи), возникает несколько проблем: помимо того, что кропотливо медленно, создание заливки df потребляет всю память (супер) компьютера, а я получить ошибку "Ошибка: не может выделить вектор размером 1529.0 Гб"

Как мне решить проблему? Большое спасибо!

library(dplyr)
library(tidyr)
libray(bigmemory)

candidate_id <- c("cand_1","cand_1","cand_1","cand_2","cand_3")
donor_id <- c("don_1","don_1","don_2","don_2","don_3")
donation <- c(1,2,3.5,4,10)
df = data.frame(candidate_id,donor_id,donation)
colnames(df) <- c("candidate_id","donor_id","donation")

fill <- df %>% 
 group_by(df$candidate_id,df$donor_id) %>% 
 summarise(tot_donation=sum(as.numeric(donation))) %>%
 complete(df$candidate_id,df$donor_id)

fill <- unique(fill[ ,1:3])
colnames(fill) <- c("candidate_id","donor_id","tot_donation")

nrow = length(unique(df$candidate_id))
ncol = length(unique(df$donor_id))
row_names = unique(fill$candidate_id)
col_names = unique(fill$donor_id)

x <- big.matrix(nrow, ncol, init=NA,dimnames=list(row_names,col_names))

for (i in 1:nrow){
 for (j in 1:ncol){

 x[i,j] <- fill[which(fill$candidate_id == row_names[i] & 
 fill$donor_id == col_names[j]), 3]
 }
}
2 ответа

Я вижу, что вы используете unique потому что ваш вывод имеет дублированные значения. Исходя из этого вопроса, вы должны попробовать следующее, чтобы избежать дублирования:

fill <- df %>% 
 group_by(candidate_id, donor_id) %>% 
 summarise(tot_donation=sum(donation)) %>%
 ungroup %>%
 complete(candidate_id, donor_id)

Можете ли вы затем попытаться создать желаемый результат? Я думаю, что unique может быть очень ресурсоемким, поэтому постарайтесь не называть его. tidyr версия того, что предложил Бенджамин, должна быть:

spread(fill, donor_id, tot_donation)

EDIT: Кстати, поскольку вы отметили вопрос с sparse-matrix, вы действительно можете использовать разреженность в своих интересах:

library(Matrix)
library(dplyr)

df <- data.frame(
 candidate_id = c("cand_1","cand_1","cand_1","cand_2","cand_3"),
 donor_id = c("don_1","don_1","don_2","don_2","don_3"),
 donation = c(1,2,3.5,4,10)
)

summ <- df %>% 
 group_by(candidate_id, donor_id) %>% 
 summarise(tot_donation=sum(donation)) %>%
 ungroup

num_candidates <- nlevels(df$candidate_id)
num_donors <- nlevels(df$donor_id)
smat <- Matrix(0, num_candidates, num_donors, sparse = TRUE, dimnames = list(
 levels(df$candidate_id),
 levels(df$donor_id)
))

indices <- summ %>%
 select(candidate_id, donor_id) %>%
 mutate_all(unclass) %>%
 as.matrix

smat[indices] <- summ$tot_donation
smat

3 x 3 sparse Matrix of class "dgCMatrix"
 don_1 don_2 don_3
cand_1 3 3.5 .
cand_2 . 4.0 .
cand_3 . . 10


Вы можете попробовать

library(reshape2)

dcast(fill, candidate_id ~ donor_id, 
 value.var = "tot_donation", 
 fun.aggregate = sum)

Я не знаю, если это позволит избежать проблемы памяти, но это, вероятно, будет гораздо быстрее, чем вдвое for цикл.

Я должен бежать к встрече, но часть меня задается вопросом, есть ли способ сделать это с outer.

licensed under cc by-sa 3.0 with attribution.