首页 > 解决方案 > 如何使用长数据框创建假人?

问题描述

我有一个包含 2 列和 1316171 行的数据框,但也有一个包含 2 列和 7621 行的数据框会产生问题。

myFun <- function(n = 5000) {
  a <- do.call(paste0, replicate(5, sample(LETTERS, n, TRUE), FALSE))
  paste0(a, sprintf("%04d", sample(9999, n, TRUE)), sample(LETTERS, n, TRUE))
}

m <- myFun(7021)
d <- myFun(7021)

df <-data.frame(m,d)

我想创建虚拟变量,所以我使用以下非常简单的代码:

genes2 <- fastDummies::dummy_cols(df, select_columns = "m") 

但是,我不断收到此错误消息:

 Warning message:
    In data.table::alloc.col(.data, ncol(.data) + length(unique_vals)) :
      tl (64004) is greater than 10,000 items over-allocated (l = 15170). If you didn't set the datatable.alloccol option to be very large, please report to data.table issue tracker including the result of sessionInfo()

我了解到,当您创建一个太大而无法处理的数据表时会发生这种情况,我在 StackOverflow 上发现

默认情况下 v1.8.8 :

options()$datatable.alloccol max(100, 2 * ncol(DT)) 这可能不是最好的默认值,您应该尝试将其更改为:

options(datatable.alloccol = quote(max(100L, ncol(DT)+64L))

但即使在尝试之后,我也会收到相同的错误消息。

我还了解到,您可以分配您应该使用该alloc.col函数将 data.table 中所需的列数量预先分配给一个大于预期 ncol 的数字。

例如:

alloc.col(myDataTable, 7021)

但不幸的是,这对我来说不起作用,可能是因为我在fastDummies代码之前或之后使用它。

如何创建虚拟变量并以功能方式分配列数?

标签: rdataframedatatable

解决方案


一个不完整的答案,但渴望评论。 tl; dr您的完整问题将遇到大内存问题,可以通过使用稀疏矩阵来缓解。

  • 这是一个警告,而不是错误:值得尝试理解和解决它,但它实际上不应该妨碍做任何事情......?
  • 我没有收到此警告(我使用的是data.table1.12.8 版)。更新您的版本有帮助吗?
  • 我根本看不到您发布的代码实际上将如何涉及data.table(尽管如果您开始使用df <- data.table(m,d)而不是 using data.frame())?

但是,如果您打算将此扩展到 1316171 行,则可能会遇到更大的问题。您给出的示例创建了一个 190-Mb 的对象:

format(object.size(genes2),"Mb") ## 190.4 Mb

我们可以通过计算得到这个数字7021 (number of rows) * 7021 (number of columns; see below) * 4 (bytes per integer) / 2^20 (bytes per Mb)

n <- 7021
n*n*4/2^20 ## 188.80434

实际对象要大一些,因为 (1)fast_dummies保留了两列字符向量md以及;(2) 有一点开销。

在您的示例中,每一行都是唯一的(因为您从中生成“基因名称”的样本空间很大),因此我们最终会得到与行一样多的假人(列)。如果这对于您的完整数据集是正确的(即您有 1316171 个唯一基因名称),您最终会得到一个占用超过 6 TB空间的对象。

n <- 1316171
n*n*4/2^40   ## 6.3

这可能是可管理的,但可能无法使用本地硬件资源。

也许你只有 10,000 个不同的基因名称?在这种情况下,您将需要:

m <- 1e4
m*n*4/2^30  ## 49 Gigabytes

处理 49 Gb 对象是合理的,但仍然超出了大多数标准硬件的范围(如果您实际上想要对该对象执行任何操作,而不仅仅是将其存储在内存中,则您将需要该内存大小的几倍)。

(我使用的是稍微老式的约定,即 1 Kb=2^10 字节、1 Mb=2^20、1 Gb = 2^30、1 Tb = 2^40)。

如果您打算在下游使用的机器将支持稀疏矩阵,那么我强烈建议您将虚拟矩阵构建为稀疏矩阵,例如:

f2 <- Matrix:::fac2sparse(myFun(7021))
dim(f2)  ## 7021 7021
object.size(f2) ## 619400 bytes

这是 620 KB,而不是之前的 188 Mb。

您的全尺寸问题的虚拟矩阵需要不到 20 秒的时间来构建(在笔记本电脑上)和 111 Mb 来存储:

system.time(f3 <- Matrix:::fac2sparse(myFun(1316171)))
format(object.size(f3),"Mb")

推荐阅读