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

时间:2012-12-28 19:09:16

标签: r

我正在尝试使用大表(大约9400万行,3列)进行一些基本计算,这需要在R中使用像ff这样的包。但是,我在使用这个包时遇到了麻烦记忆,虽然我知道我的电脑能够处理这个问题。我在下面列出了我的硬件/软件规格,以及我的代码似乎没有正确使用ff包。我花了100多个小时阅读每个pdf,ppt和网站,提到ff包装上的任何内容,我没有找到任何解释如何清楚地使用ff(至少对像我这样的业余爱好者)。对我所做错的任何帮助都将不胜感激。当我计算到大约110万行时,这种逻辑似乎有效,但之后它似乎超出了界限。

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

硬件/软件规格:

  • 2012年6月Macbook Pro配备16 GB RAM,i7四核处理器,512 GB SSD
  • OS X 10.8.2
  • 使用32位R程序

数据/桌子:

  • 名为“Trades.txt”的文本文件有94,741,221行,三列
  • 第1列名为TradePosition(“因子”类型,级别/值=“0”,“短”或“长”)
  • 第2列名为ShortPrice(“双”类型,值代表欧元/美元货币价格至小数点后5位)
  • 第3列名为LongPrice(“双”类型,值代表欧元/美元货币价格至小数点后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
}

2 个答案:

答案 0 :(得分:5)

第一句话:如果你有16Gb的RAM,你运行32位版本的R是一个很小的问题,为什么64位版本不能完全使用呢?

对于你的问题:正如Henrico指出的那样,你没有正确使用ff和R.循环R中的每一行不是做事的方式,不是在ff中,而不是在基础R中。你需要向量化你的代码。我建议你遵循与处理大数据无关的R课程,但要遵循R数据处理的基本概念。

除了那个评论之外,这里是您在ff中使用包ffbase中的一些额外实用程序寻找的内容。请注意我没有看到你对Short / Long和乘法的确切说明,但是ffifelse可以根据你的需要进行更改,就像你在R的基础包中使用正常的ifelse一样。 祝你好运ff。

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))

答案 1 :(得分:4)

以下是(IMHO精湛)幻灯片的链接,描述了如何在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用户组的谈话,并详细介绍了处理大型数据集的不同方法。他们专注于bigmemory,但ff也很有特色。

我和之前的一些评论者一样,更喜欢大记忆方法。主要是因为它更容易找到可用的文档。具体来说,从上面的幻灯片中处理航空公司数据示例是相当令人大开眼界的。

然后,根据您的情况,而不是粗暴强迫它,也尝试大量样本的9500万行可能足以得出有意义的结论。

祝你好运!