r如何在大型数据集的简单'for'循环中使用 ff 包



我正试图用一个大表(~ 9400万行,3列)做一些基本的计算,需要使用像r中的ff这样的包。然而,我在使用这个包和内存不足时遇到了麻烦,虽然我知道我的计算机有能力处理这个问题。我在下面包括了我的硬件/软件规格,以及我的代码,似乎没有正确地使用ff包。我花了100多个小时阅读每一个提到ff包的pdf、ppt和网站,但我还没有找到任何能清楚地解释如何使用ff的东西(至少对我这样的业余爱好者来说)。任何帮助我做错了,我将不胜感激。当我计算到大约110万行时,这种逻辑似乎是有效的,但之后似乎就越界了。

我也试过将'for'循环分解成总大小的1/200块;为现有的ShortPrice &amp创建新的ff对象;在每次循环时,使用LongPrice ff文件,然后在每次循环结束时使用rm(), gc()。当我在开始时通过read.table.ffdf为每列创建ff文件时,由于某种原因,当尝试使用vmode = "quad", "integer"或"raw"为现有的TradePosition ff文件创建新的ff对象时,我丢失了TradePosition值。

硬件/软件规格:

  • 2012年6月Macbook Pro, 16gb RAM, i7四核处理器,512gb SSD
  • os x 10.8.2
  • 使用32位R程序
数据/表:

  • 名为"Trades.txt"的文本文件有94,741,221行,三列
  • 列1名为TradePosition ("factor"类型,水平/值= "0","Short"或"Long")
  • 第2列命名为ShortPrice("double"类型,值表示欧元/美元货币价格到小数点后5位)
  • 第3列命名为LongPrice("double"类型,值表示欧元/美元货币价格到小数点后5位)
  • 内部R变量"DatasetLength" = 94,741,221
代码:

library(ff)
options("fftempdir"="/Users/neil/Code/","ffbatchbytes"=20*getOption("ffbatchbytes"),"ffmaxbytes"=8*getOption("ffmaxbytes"),"ffpagesize"=1000*65536,"ffcaching"="mmnoflush")
ffdfTrades <- read.table.ffdf(file="/Users/neil/Code/Trades.txt",nrows=DatasetLength,FUN="read.table",header=TRUE,sep=";",quote="",colClasses=c("factor","numeric","numeric"),comment.char="")
Transactions <- c(rep(0,DatasetLength))
dataindex <- 1
for (dataindex in seq(1,DatasetLength-1,1)) {
    if (ffdfTrades$TradePosition[dataindex]!=ffdfTrades$TradePosition[dataindex+1]) {
        if (ffdfTrades$TradePosition[dataindex+1]=="Short") {
            if (ffdfTrades$TradePosition[dataindex]=="Long") {
                Transactions[dataindex+1] <- -2*ffdfTrades$ShortPrice[dataindex+1]
            }
            else {
                Transactions[dataindex+1] <- -1*ffdfTrades$ShortPrice[dataindex+1]
            }
        }
        else {
            if (ffdfTrades$TradePosition[dataindex+1]=="Long") {
                if (ffdfTrades$TradePosition[dataindex]=="Short") {
                    Transactions[dataindex+1] <- 2*ffdfTrades$LongPrice[dataindex+1]
                }
                else {
                    Transactions[dataindex+1] <- 1*ffdfTrades$LongPrice[dataindex+1]
                }
            }
        }
    }
    message(paste("Row ",dataindex," done.",sep=""))
    dataindex <- dataindex + 1
}

第一句话:很遗憾,如果你有16Gb的内存,你运行32位版本的R,为什么不运行64位版本来充分利用它?

对于你的问题:正如Henrico指出的那样,你没有适当地使用ff和R。循环遍历R中的每一行不是处理事情的方法,在ff中不是,在R中也不是,你需要向量化你的代码。我建议你学习一门与处理大数据无关的R课程,而是关于R数据处理的基本概念。

除了这个注释之外,下面是您在ff中使用软件包ffbase中的一些额外实用程序寻找的内容。请注意,我没有查看您对Short/Long和乘法的确切规范,但是ffifelse可以根据您的需要进行更改,就像您在R的基本包中使用普通的ifelse一样。祝你好运。

size <- 1000000
trades <- data.frame(TradePosition = factor(sample(c("0","Short","Long"), size, replace=TRUE)), ShortPrice = rnorm(size), LongPrice = rnorm(size))
write.table(trades, file = "Trades.txt", sep=";", row.names=FALSE)
require(ff)
require(ffbase)
trades <- read.table.ffdf(file="Trades.txt", sep=";", header=TRUE, colClasses=c("factor","numeric","numeric"))
idx <- cumsum(ff(1, length=nrow(trades)))
idx <- ffwhich(idx, idx < nrow(trades))
trades$previousposition <- c(ff(factor(NA)), trades$TradePosition[idx])
yourmultiplier <- 2
yourothermultiplier <- -1
trades$transactions <- ffifelse(trades$TradePosition == "Long", 
                            ffifelse(trades$previousposition == "Short", yourmultiplier*trades$ShortPrice, trades$ShortPrice),
                            ffifelse(trades$previousposition == "Long", yourothermultiplier*trades$LongPrice, trades$LongPrice))

以下是介绍如何在r中使用大数据的幻灯片链接。

http://www.bytemining.com/2010/07/taking-r-to-the-limit-part-i-parallelization-in-r/http://www.bytemining.com/2010/08/taking-r-to-the-limit-part-ii-large-datasets-in-r/

两者都来自于对R用户组的演讲,并详细介绍了处理大型数据集的不同方法。它们关注的是大内存,但ff也有特色。

我,像之前的一些评论者一样,更喜欢大内存方法。主要是因为它更容易找到可用的文档。具体来说,通过上面幻灯片中的航空公司数据示例可以让人大开眼界。

然后,根据您的场景,尝试9500万行的大样本可能足以得出有意义的结论,而不是强制执行。

祝你好运!

最新更新