【问题标题】:Bind data.frames row-wise in R without creating copies在 R 中逐行绑定 data.frames 而不创建副本
【发布时间】:2016-08-20 14:32:09
【问题描述】:

我有大量 data.frames 需要按列成对绑定,然后按行绑定,然后再输入预测模型。由于不会修改任何值,我希望最终的 data.frame 指向我列表中的原始 data.frames。

例如:

library(pryr)

#individual dataframes
df1 <- data.frame(a=1:1e6+0, b=1:1e6+1)
df2 <- data.frame(a=1:1e6+2, b=1:1e6+3)
df3 <- data.frame(a=1:1e6+4, b=1:1e6+5)

#each occupy 16MB
object_size(df1)  # 16 MB
object_size(df2)  # 16 MB
object_size(df3)  # 16 MB
object_size(df1, df2, df3)  # 48 MB

#will be in a named list
dfs <- list(df1=df1, df2=df2, df3=df3)

#putting into list doesn't create a copy
object_size(df1, df2, df3, dfs)  #48MB

最终的 data.frame 将具有此方向(每对唯一的 data.frames 由列绑定,然后对由行绑定):

df1, df2
df1, df3
df2, df3

我目前正在这样实现:

#generate unique df combinations
df_names <- names(dfs)
pairs <- combn(df_names, 2, simplify=FALSE)

#bind dfs by columns
combo_dfs <- lapply(pairs, function(x) cbind(dfs[[x[1]]], dfs[[x[2]]]))

#no copies created yet
object_size(dfs, combo_dfs)  # 48MB

#bind dfs by rows
combo_df <- do.call(rbind, combo_dfs)

#now data gets copied
object_size(combo_df)  # 96 MB
object_size(dfs, combo_df)  # 144 MB

如何避免复制我的数据但仍能获得相同的最终结果?

【问题讨论】:

  • 不要认为你可以。在第一次操作中,您只是将 R 对象从一个列表“移动”到另一个列表(data.frame 的一列本身就是一个 R 对象)。最后一步涉及创建新对象(combo_df 的列),其中顺便包含两个现有对象的数据。需要一份副本。 R 中的向量连续地存储其数据;您不能创建一个向量,其中一部分数据指向一个区域,另一部分指向另一个区域。

标签: r memory dataframe clone pryr


【解决方案1】:

按您希望的方式存储值需要 R 对数据帧进行一些压缩。我不相信数据帧支持压缩。

如果您希望以这种方式存储数据的动机是难以将其放入内存中,您可以尝试ff package。这将允许您以更紧凑的方式将其存储在磁盘上。 ffdf 类似乎具有您需要的属性:

默认情况下,创建“ffdf”对象不会创建新的 ff 文件,而是引用现有文件。这与 data.frame 不同,后者总是创建输入对象的副本,最明显的是在 data.frame(matrix()) 中,其中输入矩阵被转换为单列。相比之下,ffdf 会将输入矩阵物理存储为相同的矩阵,并将其虚拟映射到列。

此外,ff 包针对快速访问进行了优化。

请注意,我自己没有使用过这个包,所以我不能保证它会解决你的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-08
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 2023-01-20
    • 1970-01-01
    相关资源
    最近更新 更多