【发布时间】:2014-02-05 01:34:53
【问题描述】:
问题
我正在尝试使用我新发现的 data.table powers(永远)来计算一堆数据的频率内容,如下所示:
| Sample| Channel| Trial| Voltage|Class | Subject|
|-------:|--------:|------:|-----------:|:------|--------:|
| 1| 1| 1| -196.82253|1 | 1|
| 1| 2| 1| 488.15166|1 | 1|
| 1| 3| 1| -311.92386|1 | 1|
| 1| 4| 1| -297.06078|1 | 1|
| 1| 5| 1| -244.95824|1 | 1|
| 1| 6| 1| -265.96525|1 | 1|
| 1| 7| 1| -258.93263|1 | 1|
| 1| 8| 1| -224.07819|1 | 1|
| 1| 9| 1| -87.06051|1 | 1|
| 1| 10| 1| -183.72961|1 | 1|
大约有 5700 万行——每个变量都是整数,除了电压。 Sample 是从 1:350 开始的索引,Channel 从 1:118 开始。有 280 个试验。
样本数据
Martín 的示例数据是有效的,我相信(分类变量的数量与错误无关):
big.table <- data.table(Sample = 1:350, Channel = 1:118, Trial = letters,
Voltage = rnorm(10e5, -150, 100), Class = LETTERS, Subject = 1:20)
进程
我要做的第一件事是将键设置为 Sample,因为我希望我对单个数据系列所做的任何事情都以合理的顺序发生:
setkey(big.table,Sample)
然后,我对电压信号进行一些过滤以去除高频。 (过滤函数返回一个与其第二个参数长度相同的向量):
require(signal)
high.pass <- cheby1(cheb1ord(Wp = 0.14, Ws = 0.0156, Rp = 0.5, Rs = 10))
big.table[,Voltage:=filtfilt(high.pass,Voltage),by=Subject]
初始错误
我想看看它是否正确处理了它(即按主题、按试验、按通道、按采样顺序),所以我添加了一个包含电压列的频谱内容的列:
get.spectrum <- function(x) {
spec.obj <- spectrum(x,method="ar",plot=FALSE)
outlist <- list()
outlist$spec <- 20*log10(spec.obj$spec)
outlist$freq <- spec.obj$freq
return(outlist)
}
big.table[,c("Spectrum","Frequency"):=get.spectrum(Voltage),by=Subject]
Error: cannot allocate vector of size 6.1 Gb
我认为问题在于get.spectrum() 试图一次吃掉整个列,考虑到整个表只有大约 1.7GB。是这样吗?我有哪些选择?
你有什么尝试?
增加分组的粒度
如果我调用 get.spectrum 包括我想要分组的所有列,我会得到一个更有希望的错误:
big.table[,c("Spectrum","Frequency"):=get.spectrum(Voltage),
by=c("Subject","Trial","Channel","Sample")]
Error in ar.yw.default(x, aic = aic, order.max = order.max, na.action = na.action, :
'order.max' must be >= 1
这意味着我正在调用的 spectrum() 函数正在获取错误形状的数据。
切入点,尝试不同的“位置”条件
按照罗兰的建议,我将点数减少到2000万左右,并尝试了以下方法:
big.table[,"Spectrum":=get.spectrum(Voltage),
by=c("Subject","Trial","Channel")]
Error in `[.data.table`(big.table, , `:=`("Spectrum", get.spectrum(Voltage)), :
All items in j=list(...) should be atomic vectors or lists. If you are trying something like
j=list(.SD,newcol=mean(colA)) then use := by group instead (much quicker), or cbind or merge
afterwards.
我的想法是我不应该按样本分组,因为我想将此函数应用于上述by 向量给出的每组 350 个样本。
通过从 data.table 常见问题解答的第 2.16 节收集的一些内容对此进行改进,我添加了与ORDER BY 等效的 SQL。我知道 Sample 列需要从每个输入的 1:350 转到 spectrum() 函数:
> big.table[Sample==c(1:350),c("Spectrum","Frequency"):=as.list(get.spectrum(Voltage)),
+ by=c("Subject","Trial","Channel")]
Error in ar.yw.default(x, aic = aic, order.max = order.max, na.action = na.action, :
'order.max' must be >= 1
再次,我遇到了非唯一输入的问题。
【问题讨论】:
-
在巨大的 data.table 中使用它之前,您应该使用数据的子集进行测试。此外,如果您在 R 中处理这么多数据并且没有至少 16 GB 的 RAM,我的建议是投资更多的内存。现在没那么贵了。
-
你是对的,当然;我删掉了大部分让我在 618MB 上获得 2300 万分的主题。
-
@TrevorAlexander 如果你模拟一些数据会更容易帮助你。
-
我现在对 data.table 有足够的信心做到这一点。
-
@TrevorAlexander 我的意思是模拟一些与您正在工作的数据具有相似特征的数据,因此我们可以尝试您的代码并回答问题。
标签: r data-structures out-of-memory data.table