9

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

我还尝试将“for”循环分解为总大小的 1/200 块;在循环的每一轮中为现有的 ShortPrice & LongPrice ff 文件创建新的 ff 对象,然后在每轮结束时创建 rm()、gc()。当我在开始时通过 read.table.ffdf 为每一列创建 ff 文件时,由于某种原因,我在尝试使用 vmode = "quad", "integer 为现有 TradePosition ff 文件创建新的 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(“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
}
4

2 回答 2

6

首先说明:如果您有 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))
于 2012-12-29T01:55:55.120 回答
4

以下是介绍如何在 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 也有特色。

我和之前的一些评论者一样,更喜欢 bigmemory 方法。主要是因为更容易找到可用的文档。具体来说,通过上面幻灯片中的航空公司数据示例进行工作是相当大开眼界的。

然后,根据您的情况,而不是蛮力强制它,还尝试从 9500 万行中提取大量样本可能足以得出有意义的结论。

祝你好运!

于 2012-12-29T20:11:28.140 回答