【问题标题】:How to process a large file with 30M entries? [closed]如何处理具有 30M 条目的大文件? [关闭]
【发布时间】:2013-07-12 13:25:58
【问题描述】:

我的问题的第一部分是,有没有比计算标准差更快的方法

mySD = apply(myData,1,sd)

问题的第二部分是如何去除异常值(距离每条线的平均值 3 个 SD)并重新计算每条线的 SD。

问题的第三部分是,一旦我计算出每条线的 SD,如何挑选超过特定阈值(例如 0.05)的那些?

我的矩阵有 3000 万行和 50 列。

如果有比 R 更快的方法(例如 perl 或 matlab),我也很乐意尝试。

...

我有一个包含 3000 万行和 50 列的矩阵。对于每一行,我想删除异常值并计算标准偏差 (SD)。所以我会有3000万SD。 然后我想选择那些 SD 最高的行(前 %5)。

我尝试了 R,但即使将数据加载到 R 中也需要大量时间。我什至将数据保存为 *RData。但仍然很慢且耗时。

有没有更快的方法来做这些事情?在 r 或 perl 或 matlab 中?

【问题讨论】:

  • 当我们不知道你的方式是什么或它有多快时,“更快的方式”并没有多大意义......
  • @flodel 在这种情况下,离群值将与每条线的平均值相差 3SD。

标签: r large-files outliers large-data


【解决方案1】:

你的问题有两个部分,高效计算和处理大数据。

高效计算

假设您有一个更易于管理的数据集m,其中包含 3000 万行和 50 列的 5%(这大约占我 8Gb 的 30%;内存不足会使一切运行缓慢,因此您需要让我们知道这类信息)。

nrow <- .05 * 30000000
ncol <- 50
m <- matrix(rnorm(nrow * ncol), nrow)

也许您会编写一个函数clean,以有效地逐行删除异常值;它可能使用另一个函数来有效地计算逐行标准差

rowSD <- function(m) {
    ## efficiently calculate row-wise SD
    ## naive: apply(m, 1, sd, na.rm=TRUE)
    ## update via @BenBolker / http://stackoverflow.com/questions/16046820/change-row-values-to-zero-if-less-than-row-standard-deviation
    sqrt(rowSums((m - rowMeans(m, na.rm=TRUE))^2, na.rm=TRUE) / (ncol(m)-1))
}

clean <- function(m) {
    ## efficiently implement your strategy for identifying outliers
    m[abs(m - rowMeans(m)) > 3 * rowSD(m)] <- NA  # fast enough
    m
}

对于矩阵mrowSD(m) 的简单实现大约需要 56 秒,而来自@BenBolker 的更新大约需要 1.4 秒; clean(sd) 大约需要 5 秒。两者都制作数据的多个副本并传递数据,远非理想。

大数据

考虑以nrow 大小的块处理数据。如果你清理了两个块m1m2,你可以将它们组合起来,并保持最高值与

sd <- c(rowSD(m1), rowSD(m2))
## if sorted, sd[idx] would be the value that separate high and low
idx <- nrow(result) + nrow(m) - nrow 
keep <- sd > sort.int(sd, partial=idx)[idx]  # index correct, or off-by-one?
## replace smallest in m1 with largest in m2
m1[!head(keep, nrow(m1)),] <- m2[tail(keep, nrow(m2)),]

由于您正在执行矩阵运算,听起来您的数据都是数字的,而 scan 以块的形式读取文件是合适的输入。

conn <- file("myfile", "r")
result <- matrix(0, nrow, ncol)
while (length(x <- scan(con, nmax = nrow * ncol))) {
    m <- clean(matrix(x, nrow, ncol, byrow=TRUE))
    sd <- c(rowSD(result), rowSD(m))
    idx <- nrow(result) + nrow(m) - nrow
    keep <- sd > sort.int(sd, partial=idx)[idx]
    result[!head(keep, nrow),] <- m[tail(keep, nrow(m)),]
}
close(conn)

result 是具有最高标准偏差的已清理行的所需集合。

【讨论】:

  • 来自 stackoverflow.com/questions/16046820/… : sdbyrow &lt;- function(mat) sqrt(rowSums((mat-rowMeans(mat))^2)/(ncol(mat)-1) ) 可能会大大加快 rowSD ... 在 1e5 x 1e2 矩阵上,时间为 6.5 秒 vs 1 秒。
  • @MartinMorgan 非常感谢,我现在正在尝试这个。我会试试这个,让你知道它是怎么回事。
  • @MartinMorgan ,第一列是文本,它是标题。如何更改 scan() 以使其成为标题?
  • 您可以在scan() 中使用skip=1(这似乎与您的问题没有直接关系??)(我猜您的意思是第一个row?)
  • @BenBolker 我正在尝试按行计算,并且每一行都有一个标题(第一列是标题)。 MartinMorgan 建议使用 scan() 更快地加载文件。但是 scan() 不喜欢我有标题。
【解决方案2】:
library(bigmemory)
?read.big.matrix

对于初学者。然后看biganalyticsbigtabulatebiglm

【讨论】:

    猜你喜欢
    • 2016-03-25
    • 2021-08-24
    • 1970-01-01
    • 2016-02-10
    • 2021-07-22
    • 1970-01-01
    • 2020-09-13
    • 2014-05-21
    • 2021-07-28
    相关资源
    最近更新 更多