我正在尝试使用准引号语法(quo
、exprs
、!!
等)以及foreach
函数,通过在rxDataStep
函数内要求值的表达式的命名列表,特别是transforms
参数,来创建几个新变量。我得到以下错误:
Error in rxLinkTransformComponents(transforms = transforms, transformFunc = transformFunc, : 'transforms' must be of the form list(...)
我有一个数据集,其中包括许多变量。为了进行进一步的分析,我需要进行日志转换。我已经使用"RevoScaleR"包中的rx
函数大约三年了,完全错过了数据转换技术的"tidyverse"/管道方法。我偶尔会接触这些工具,但更喜欢使用前面提到的rx
函数,这让我相对熟悉,而且到目前为止,它们对我很有用。
作为MWE:
所需库:
library(foreach)
library(rlang)
创建需要进行日志转换的变量。
vars <- foreach(i = 10:20, .combine = "cbind") %do% rnorm(10, i)
具有标识符和以上变量的数据帧。
data_in <- data.frame(id = 1:10, vars)
对象,该对象创建日志转换变量的表达式;这将创建一个命名列表。
log_vars <- foreach(i = names(data_in[-1]), .final = function(x) set_names(x, paste0(names(data_in[-1]), "_log"))) %do%
expr(log10(!!sym(i)))
现在尝试将变量添加到现有的数据帧中。
data_out <- rxDataStep(inData = data_in, transforms = log_vars, transformObjects = list(log_vars = log_vars))
由此产生的错误如下:
Error in rxLinkTransformComponents(transforms = transforms, transformFunc = transformFunc, : 'transforms' must be of the form list(...)
鉴于log_vars
被定义为命名列表,我根本无法理解这个错误。可以用CCD_ 10和CCD_。
我尝试了一种稍微不同的方式来定义新变量:
log_vars <- unlist(foreach(i = names(data_in[-1]), j = paste0(names(data_in[-1]), "_log")) %do%
exprs(!!j := log10(!!sym(i))))
我必须使用unlist
,因为exprs
已经提供了一个列表作为输出。不管怎样,我都会得到和以前一样的错误。
当然,我希望在数据帧中插入10个名为result.1_log, result.2_log
等的新变量。相反,我收到了上面的错误,并且没有创建新的数据帧。
我怀疑rx
函数不喜欢使用准引号语法,然而,我以前在必须识别具有某些变量NA值的主体时使用过它。这是使用rxDataStep
的rowSelection
自变量完成的。我确实意识到rowSelection
需要一个单一的逻辑表达式,而transforms
需要一个命名的表达式列表。
任何帮助都将不胜感激,因为这种类型的数据转换将在我的分析中再次出现。我确实怀疑我只是不了解准引号语法的内部工作原理,或者列表通常是如何工作的,但希望有一个简单的解决方案。
我使用的是Microsoft R Open 3.4.3。
我的会话信息如下:
R Services Information:
Local R: C:Program FilesMicrosoftML ServerR_SERVER
Version: 1.3.40517.1016
Operating System: Microsoft Windows 10.0.17134
CPU Count: 4
Physical Memory: 12169 MB, 6810 MB free
Virtual Memory: 14025 MB, 7984 MB free
Video controller[1]: Intel(R) HD Graphics 620
GPU[1]: Intel(R) HD Graphics Family
Video memory[1]: 1024 MB
Connected users: 1
我不太确定你想做什么,因为我认为你把事情弄得太复杂了。如果您只想记录每个数据点中每个#的日志,那么我将在下面展示两种方法。
- 方法#1是静态的,你知道固定的列数和硬代码。用这种方法运行rxDataStep会快一点
- 方法#2更加动态,利用了transformFunc。transformFunc是分块工作的,因此可以以集群的方式安全地使用它。rxDataStep知道如何将块集成在一起。但它的表现会受到一些冲击
- 您可能一直在尝试找到一种混合方法——在rxDataStep中动态构建transforms参数的列表。我还没有找到一种方法让它发挥作用。在rxSetVarInfo中也有类似的问题(用rxSetVarInfo更改动态变量名),但使用这种方法对我来说还没有成功
如果我完全没有达到目标,请告诉我!
library(foreach)
library(rlang)
startSize <- 10
endSize <- 20
vars <- foreach(i = startSize:endSize, .combine = "cbind") %do% rnorm(10, i)
data_in <- data.frame(vars)
tempInput <- tempfile(fileext = ".xdf")
tempOutput <- tempfile(fileext = ".xdf")
rxImport(inData = data_in, outFile = tempInput, overwrite = T)
rxGetInfo(tempInput, getVarInfo = T)
### Approach #1
print("Approach #1")
rxDataStep(inData = tempInput, outFile = tempOutput, overwrite = T,
transforms = list(
log_R1 = log10(result.1),
log_R2 = log10(result.2),
log_R3 = log10(result.3),
log_R4 = log10(result.4),
log_R5 = log10(result.5),
log_R6 = log10(result.6),
log_R7 = log10(result.7),
log_R8 = log10(result.8),
log_R9 = log10(result.9),
log_R10 = log10(result.10),
log_R11 = log10(result.11)))
rxGetInfo(tempOutput, getVarInfo = T)
### Approach #2
print("Approach #2")
logxform <- function(dataList) {
numRowsInChunk <- length(dataList$result.1)
for (j in 1:columnDepth) {
dataList[[paste0("log_R",j)]] <- rep(0, times=numRowsInChunk)
for (i in 1:numRowsInChunk) {
dataList[[paste0("log_R",j)]][i] <- log10(dataList[[paste0("result.",j)]][i])
}
}
return(dataList)
}
rxDataStep(inData = tempInput, outFile = tempOutput, overwrite = T,
transformObjects = list(columnDepth = endSize - startSize + 1),
transformFunc = logxform)
rxGetInfo(tempOutput, getVarInfo = T)