rxDataStep "преобразовать" аргумент, используя квази-кавычку
Я пытаюсь использовать синтаксис квази-цитата (quo
, exprs
, !!
и т. д.), а также foreach
функция для создания нескольких новых переменных с помощью именованного списка выражений, которые будут оцениваться внутри rxDataStep
функция, в частности, transforms
аргумент. Я получаю следующую ошибку:
Error in rxLinkTransformComponents(transforms = transforms, transformFunc = transformFunc, : 'transforms' must be of the form list(...)
У меня есть набор данных, который включает в себя ряд переменных, которые мне нужно преобразовать в журнал для проведения дальнейшего анализа. Я использовал rx
функции из пакета "RevoScaleR" в течение примерно трех лет и полностью пропустили "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
определяется как именованный список. Можно проверить это с str
а также typeof
,
Я попробовал немного другой способ определения новых переменных:
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 определенных переменных. Это было сделано с помощью rowSelection
аргумент rxDataStep
, Я понимаю, что rowSelection
требует одного логического выражения, в то время как transforms
требует именованного списка выражений.
Любая помощь будет принята с благодарностью, так как этот тип преобразования данных будет постоянно поддерживаться в моем анализе. Я подозреваю, что я просто не понимаю внутреннюю работу синтаксиса квази-цитаты или, возможно, как списки работают в целом, но, надеюсь, есть простое исправление.
Я использую Microsoft R Open 3.4.3.
Информация о моей сессии следующая:
R Services Information:
Local R: C:\Program Files\Microsoft\ML Server\R_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 ответ
Я не совсем уверен, что вы пытаетесь сделать, потому что я думаю, что вы сделали вещи слишком сложными. Если все, что вы хотите сделать, это взять журнал каждого # в каждой точке данных, то я покажу два подхода ниже.
- Подход № 1 является статическим, вы знаете фиксированное количество столбцов и жестко кодируете его. При таком подходе rxDataStep работает немного быстрее.
- Подход №2 немного более динамичен, используя преимущества transformFunc. transformFunc работает порциями, поэтому его можно безопасно использовать в кластерном режиме. rxDataStep знает, как объединить фрагменты вместе. Но для этого будет некоторый удар по производительности.
- Возможно, вы пытались найти гибридный подход - динамически создать список для параметра transforms в rxDataStep. Я не нашел способ заставить это работать. Вот аналогичный вопрос для выполнения этого в 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)