大数据集的ivot_wider替代方案

Sco*_*ert 7 r tidyr

我有一个需要整理的大型数据集(35.8 GB,超过 10 亿行)。

这是一些可重现的代码来显示其格式。

id <- c(1, 1, 2, 2)
item <- c("a1", "a2", "a1", "a2")
itemformat <- c("AA", "AB", "BB", "AB")
full <- cbind(id, item, itemformat)
full <- as.data.table(full)
full
Run Code Online (Sandbox Code Playgroud)

此代码适用于此示例:

full2 <- full %>% 
  pivot_wider(names_from = item, values_from = itemformat)
full2
Run Code Online (Sandbox Code Playgroud)

然而,当在海量数据集上使用此方法时,R 要么说大小为 3.8 GB 的向量太大(我重新启动 R 并使用 gc() 函数),要么直接崩溃(工作超过 30 分钟后)。

我注意到data.table包中的fread()fwrite()比我使用过的其他任何东西(例如read.csv()read_csv() )要快得多。

那么,有没有一种方法(也许是根据data.table包?)将这些数据重新排列为大约 800,000 列?

另外,800,000 列是否超出某种限制?

整理完毕后,文件大小应该会减小(希望如此)。

旁注:我有 64 GB 的 RAM。

谢谢你!

zep*_*ryl 7

我基本上同意这样的评论,即如此大的数据集很难在本地使用。也就是说,您可以尝试按块进行旋转,将每个块保存到磁盘,然后重新加载并绑定所有旋转的块。

\n
set.seed(13)\nlibrary(tidyr)\nlibrary(dplyr)\nlibrary(purrr)\n\n# example data: 9 cases with 3 SNPs each\n(data_long <- expand_grid(id = 1:9, item = paste0("a", 1:3)) |>\n  mutate(itemformat = sample(c("AA", "AB", "BB"), 27, replace = TRUE)))\n#> # A tibble: 27 \xc3\x97 3\n#>       id item  itemformat\n#>    <int> <chr> <chr>     \n#>  1     1 a1    BB        \n#>  2     1 a2    AA        \n#>  3     1 a3    AB        \n#>  4     2 a1    AA        \n#>  5     2 a2    AB        \n#>  6     2 a3    AB        \n#>  7     3 a1    AA        \n#>  8     3 a2    BB        \n#>  9     3 a3    AA        \n#> 10     4 a1    AB        \n#> # \xe2\x80\xa6 with 17 more rows\n\n# define chunks to process 3 cases at a time\nids <- unique(data_long$id)\ncases_per_chunk <- 3\nchunks <- tibble(\n    start = seq(length(ids), by = cases_per_chunk),\n    stop = start + cases_per_chunk - 1\n  ) |>\n  mutate(filename = paste0("SNPs_wide", row_number(), ".rds"))\n\n# pivot and save in chunks of 3 cases\npwalk(chunks, \\(start, stop, filename) {\n  data_long |>\n    filter(id %in% ids[start:stop]) |>\n    pivot_wider(names_from = item, values_from = itemformat) |>\n    saveRDS(filename)\n})\n\n# load pivoted chunks and row-bind\n(data_wide <- map_dfr(chunks$filename, readRDS))\n#> # A tibble: 9 \xc3\x97 4\n#>      id a1    a2    a3   \n#>   <int> <chr> <chr> <chr>\n#> 1     1 BB    AA    AB   \n#> 2     2 AA    AB    AB   \n#> 3     3 AA    BB    AA   \n#> 4     4 AB    BB    BB   \n#> 5     5 BB    AA    AA   \n#> 6     6 AB    AA    BB   \n#> 7     7 AA    AA    BB   \n#> 8     8 BB    AB    AA   \n#> 9     9 AA    BB    BB\n
Run Code Online (Sandbox Code Playgroud)\n

创建于 2022 年 10 月 20 日,使用reprex v2.0.2

\n

其他一些想法:

\n
    \n
  • 您还可以修改以块的形式读取初始数据集(例如一次 800K 行),然后按上述方式旋转并保存每个块。
  • \n
  • 针对大型数据集优化的工具(例如arrow)可能值得一看。
  • \n
  • 这些数据从哪里来?是否有可能,或者更容易,在上游做一些事情来将数据转换为宽格式?
  • \n
  • 我对Bioconductor了解不多,但它是一个专注于 R 中生物信息学工具的项目,所以如果你还没有的话,我会在那里闲逛。
  • \n
\n

  • 感谢您的详尽评论!我没有收到通知,所以我已经能够使用 dcast() 整理数据,但我想您的答案将来会帮助其他人。如果我再次遇到类似的问题,它也可能对我有帮助。此外,由于数据更宽且更整洁,现在已降至 3 GB 以下,这更易于管理。不管怎样,再次感谢! (2认同)

Sco*_*ert 2

更新:我能够用这种格式做到这一点:

full2 <- full %>% 
  dcast(id ~ item, value.names = "itemformat")
full2
Run Code Online (Sandbox Code Playgroud)

我删除了我的实际代码(愚蠢的想法),但我相信这是我使用的格式。它适用于示例数据集。它非常快并且适用于 2 个不同的大型数据集。