使用3列创建唯一ID时的内存大小错误

时间:2018-12-30 21:05:06

标签: r dataframe matrix unique

我想在R中基于序列号,pnum和daynum的三列创建一个唯一的ID,以便它们创建一个唯一的人日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

有什么建议吗?

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:0)

您可以使用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))))

尝试一下,让我知道结果