gpt4 book ai didi

r - 将非平凡函数应用于 data.table 的有序子集

转载 作者:行者123 更新时间:2023-12-04 16:41:46 25 4
gpt4 key购买 nike

问题

我正在尝试使用我新发现的 data.table 功能(永远)来计算一堆数据的频率内容,如下所示:

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

初始错误

我想看看是否正确处理了它(即逐个主题、逐个试验、逐个 channel 、按样本顺序),所以我添加了一个包含电压列的光谱内容的列:

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() 函数正在获取错误形状的数据。

削减点,尝试不同的“where”条件

听从 Roland 的建议,我将点数减少到 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。我知道对于 spectrum() 函数的每个输入,Sample 列需要从 1:350 开始:

> 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

再次,我遇到了非唯一输入的问题。

最佳答案

也许这可以开始解决问题:

I believe the error data.table gives is because get.spectrum returns a list with:
spec and freq.

Using this example dataset:
big.table <- data.table(Sample = 1:350, Channel = 1:118, Trial = letters,
Voltage = rnorm(10e5, -150, 100), Class = LETTERS, Subject = 1:20)

str(big.table)
setkey(big.table,Sample)

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

VT <- get.spectrum(big.table$Voltage)
str(VT)

# Then you should decide which value you would like to inset in big.table
get.spectrum(big.table$Voltage)$spec
# or
get.spectrum(big.table$Voltage)$freq

这应该有效。您还可以使用 set()

big.table[, Spectrum:= get.spectrum(Voltage)$spec, by=Subject]
big.table[, Frequency:= get.spectrum(Voltage)$freq, by=Subject]

编辑如评论中所述,我尝试使用 set() 提供答案,但我看不到如何“分组依据”主题:这是我尝试过的,不确定它是否是预期的答案。

cols = c("spec", "freq")
for(inx in cols){
set(big.table, i=NULL, j=j ,value = get.spectrum(big.table[["Voltage"]])[inx])
}

编辑2两个函数,每个列一个。使用按变量分组的不同组合。

spec_fun <- function(x) {
spec.obj <- spectrum(x,method="ar",plot=FALSE)
spec <- 20*log10(spec.obj$spec)
spec
}

freq_fun <- function(x) {
freq <- spectrum(x,method="ar",plot=FALSE)$freq
freq
}

big.table[, Spectrum:= spec_fun(Voltage), by=c("Subject","Trial","Channel")]
big.table[, Frequency:= freq_fun(Voltage), by=c("Subject","Trial","Channel")]

# It gives some warnings(), probaby because of the made up data.

关于r - 将非平凡函数应用于 data.table 的有序子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21156801/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com