【问题标题】:Optimal ordering of rows/columns to reduce size of R data.frame object行/列的最佳排序以减小 R data.frame 对象的大小
【发布时间】:2018-02-27 21:06:16
【问题描述】:

是否有一种好的方法或算法来确定行和列的最佳排序和排列,以最小化磁盘上 R data.frame 的文件大小?

考虑以下数据:

# Init
library(dplyr)
set.seed(12345)
n_rows <- 10e6

df_1 <- data.frame(
    V1 = sample(1:10, n_rows, replace=TRUE),
    V2 = sample(1:2, n_rows, replace=TRUE),
    V3 = sample(1:100, n_rows, replace=TRUE),
    V4 = sample(1:1000, n_rows, replace=TRUE),
    V5 = sample(1:5, n_rows, replace=TRUE)
) %>% as_data_frame()

df_2 <- df_1 %>% arrange(
    V2,    V5,    V1,    V3,    V4
)

df_3 <- df_2 %>% select(
    V2,    V5,    V1,    V3,    V4
)

saveRDS(df_1, "temp_1.RDS")
saveRDS(df_2, "temp_2.RDS")
saveRDS(df_3, "temp_3.RDS")

输出文件大小为:

  • df_1 / temp_1.RDS = 43,770 KB
  • df_2 / temp_2.RDS = 10,091 KB
  • df_3 / temp_3.RDS = 10,089 KB

在此设置中,通过以合理的方式对行进行排序,我们观察到文件大小显着减小,通过在排列行后以“某种”方式对列进行排序,文件大小略有减小。

是否有一种自动方法可以计算出列的最佳顺序以及排列它们的最佳顺序?该方法可能使用动态编程或其他东西,但我希望那里有一个 R 包,它有一个现成的实现。

一旦加载到内存中,预先安排的对象通常性能更高吗?我猜是做与预先安排的分组一致的事情。

编辑,出于兴趣,这里有一些简单任务的计时结果:

# Do a process on a data.frame
process_func <- function(x){
    x %>% group_by(
        V2,V5,V1
    ) %>% summarise(
        sum(V4),
        sum(V3)
    )
}

system.time(replicate(100, process_func(df_1)))
system.time(replicate(100, process_func(df_2)))
system.time(replicate(100, process_func(df_3)))

同样的任务需要(重复 100 次):

  • df_1 95 秒
  • df_2 上 47 秒
  • df_3 48 秒

【问题讨论】:

  • 默认情况下,saveRDS 具有 compress = TRUE。如果您的问题是特定于将数据存储到磁盘的那种方式(我假设这是因为它太笼统了),那么基本上您是在问压缩是如何工作的(是的,当然这将受益于排序)
  • 我知道 .rds 文件是压缩的,但是有没有一种方法可以在不反复试验的情况下确定最佳排列?甚至是一个很好的启发式方法?

标签: r dataframe optimization


【解决方案1】:

作为一个很好的启发式方法,我会首先按具有较少不同值的列进行排序。更优的解决方案将需要更多的计算时间,考虑到您的问题的规模,这将是困难的。

你可以这样做:

df_4 <- df_1 %>% 
  arrange_at(., names(sort(sapply(., n_distinct))))

【讨论】:

  • 我想这在大多数情况下可能工作得很好。虽然,我假设肯定有一些计算机科学、数据库等研究人员已经研究了数据集的最大可压缩性。
猜你喜欢
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 2022-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多