【问题标题】:Memory size error when creating unique id using 3 columns使用 3 列创建唯一 ID 时出现内存大小错误
【发布时间】:2018-12-30 21:05:05
【问题描述】:

我想在R中基于serial、pnum和daynum三列创建一个唯一的ID,以便它们创建一个唯一的person-day ID。

我正在使用大型数据集,并且 do.call(interaction, df1) 产生错误:无法分配大小为 11.1gb 的向量。

serial         pnum daynum
11011202        1   1
11011202        1   2
11011202        4   1
11011202        4   2
11011203        1   1
11011203        1   2
11011207        1   1
11011207        1   2
11011207        2   1
11011207        2   2
11011209        1   1
11011209        1   2
11011209        2   1
11011209        2   2

有什么建议吗?

【问题讨论】:

  • 试试do.call(paste, df1) 或do.call(interaction, df1)
  • @akrun 谢谢,我使用了 do.call(interaction, df1) 但收到以下错误错误:无法分配大小为 11.1 Gb 的向量
  • 这意味着你有一个大数据集并且内存有问题
  • @akrun 我尝试了 memory.size() 仍然无法正常工作我还能尝试什么?
  • 你可能需要更多内存

标签: r dataframe matrix unique


【解决方案1】:

也许哈希函数就是您所追求的。
下面的代码将使用包hashFunction。它有 3 个不同的散列函数,我用murmur3.32 进行了测试,它产生 32 位散列。

首先是问题中数据的示例用法..

library(hashFunction)

apply(df1, 1, function(x) murmur3.32(paste(x, collapse = "")))

现在是一个更大的数据集。

serial <- rep(11011200 + 1:1000000, each = 4)
n <- length(serial)
pnum = rep(rep(1:2, each = 2), length.out = n)
daynum <- rep(1:2, length.out = n)

df2 <- data.frame(serial, pnum, daynum)
sum(duplicated(df2))
#[1] 0

使用较大的df2 进行测试。矩阵访问时间比 df 快,所以我将 df2 强制转换为矩阵..

system.time({
  h <- apply(as.matrix(df2), 1, function(x) murmur3.32(paste(x, collapse = "")))
})
#     user    system   elapsed
#   74.199     0.059    74.289

现在尝试先保留内存并在for 循环中分配值。

system.time({
  h2 <- integer(n)
  tmp <- as.matrix(df2)
  for(i in seq_len(n)) 
    h2[i] <- murmur3.32(paste(tmp[i, ], collapse = ""))
  rm(tmp)
})
#     user    system   elapsed
#   67.321     0.045    67.406 

identical(h, h2)
#[1] TRUE

object.size(df2)
#64000984 bytes

object.size(h)
#16000048 bytes

哈希向量比数据帧小 4 倍。

数据。

df1 <- read.table(text = "
serial         pnum daynum
11011202        1   1
11011202        1   2
11011202        4   1
11011202        4   2
11011203        1   1
11011203        1   2
11011207        1   1
11011207        1   2
11011207        2   1
11011207        2   2
11011209        1   1
11011209        1   2
11011209        2   1
11011209        2   2                  
", header = TRUE)

【讨论】:

  • 感谢您的帮助;你能解释一下这个代码序列
  • @RforBegginer 创建一个向量11011200 + 1,然后是11011200 + 2,以此类推,每个向量重复4次。这似乎或多或少类似于已发布问题中的示例serial。
【解决方案2】:

您可以使用 Base R 来做到这一点。这不会占用你的内存

data1 <- read.table(text="serial         pnum daynum
11011202        1   1
11011202        1   2
11011202        4   1
11011202        4   2
11011203        1   1
11011203        1   2
11011207        1   1
11011207        1   2
11011207        2   1
11011207        2   2
11011209        1   1
11011209        1   2
11011209        2   1
11011209        2   2",header = T)


data1$id <- as.integer(factor(with(data1, paste(serial, pnum,daynum))))

试试这个,然后告诉我结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 2021-07-14
    • 1970-01-01
    相关资源
    最近更新 更多