数据框对于超级计算机而言太大

时间:2018-07-24 15:12:17

标签: r dplyr sparse-matrix large-data

我正在尝试创建一个捐赠者和接受者的矩阵,其中填充了每对夫妇产生的捐赠总数,以保持最终的资产净值。

它适用于小型数据集(请参见下面的玩具示例),但是当我切换到国家数据集(3m条目)时,会出现一些问题:除了非常缓慢之外,fill df的创建还消耗了(super)的所有内存。计算机,并且出现错误“错误:无法分配大小为1529.0 Gb的向量”

我应该如何解决这个问题? 非常感谢!

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 个答案:

答案 0 :(得分:0)

您可以尝试

library(reshape2)

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

我不知道它是否可以避免内存问题,但是它可能比双for循环快得多。

我必须参加会议,但是我一部分人想知道是否可以通过outer来做到这一点。

答案 1 :(得分:0)

我看到您正在使用unique,因为您的输出具有重复的值。 根据{{​​3}}, 您应该尝试以下操作以避免重复:

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)

编辑:顺便说一句,由于您用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