r - data.table:如何将字符向量传递给函数 get data.table 以将其内容视为列名?
问题描述
这是一个数据表:
library(data.table)
DT <- data.table(airquality)
这个例子产生了我想要的输出:
DT[, `:=`(New_Ozone= log(Ozone), New_Wind=log(Wind))]
如何编写函数log_those_columns
以使以下代码段输出相同的结果?
old_names <- c("Ozone", "Wind")
new_names <- c("New_Ozone", "New_Wind")
log_those_columns(DT, old_names, new_names)
请注意,我需要old_names
并且new_names
足够灵活以包含任意数量的列。
(我从关于该主题的类似 StackOverflow 问题中看到,答案可能涉及 、 、 、 和/或 的某种组合.SD
,with=F
但parse()
我eval()
似乎substitute()
无法确定要使用哪些以及在哪里使用)。
解决方案
拿起MichaelChirico 的评论,函数定义可以写成:
log_those_columns <- function(DT, cols_in, cols_new) {
DT[, (cols_new) := lapply(.SD, log), .SDcols = cols_in]
}
返回:
log_those_columns(DT, old_names, new_names)
DT
Ozone Solar.R Wind Temp Month Day New_Ozone New_Wind 1: 41 190 7.4 67 5 1 3.713572 2.001480 2: 36 118 8.0 72 5 2 3.583519 2.079442 3: 12 149 12.6 74 5 3 2.484907 2.533697 4: 18 313 11.5 62 5 4 2.890372 2.442347 5: NA NA 14.3 56 5 5 NA 2.660260 --- 149: 30 193 6.9 70 9 26 3.401197 1.931521 150: NA 145 13.2 77 9 27 NA 2.580217 151: 14 191 14.3 75 9 28 2.639057 2.660260 152: 18 131 8.0 76 9 29 2.890372 2.079442 153: 20 223 11.5 68 9 30 2.995732 2.442347
正如预期的那样。
更灵活的方法
用于转换数据的函数也可以作为参数传递:
fct_those_columns <- function(DT, cols_in, cols_new, fct) {
DT[, (cols_new) := lapply(.SD, fct), .SDcols = cols_in]
}
来电:
fct_those_columns(DT, old_names, new_names, log)
head(DT)
按预期工作:
Ozone Solar.R Wind Temp Month Day New_Ozone New_Wind 1: 41 190 7.4 67 5 1 3.713572 2.001480 2: 36 118 8.0 72 5 2 3.583519 2.079442 3: 12 149 12.6 74 5 3 2.484907 2.533697 4: 18 313 11.5 62 5 4 2.890372 2.442347 5: NA NA 14.3 56 5 5 NA 2.660260 6: 28 NA 14.9 66 5 6 3.332205 2.701361
函数名可以作为字符传递:
fct_those_columns(DT, old_names, new_names, "sqrt")
head(DT)
Ozone Solar.R Wind Temp Month Day New_Ozone New_Wind 1: 41 190 7.4 67 5 1 6.403124 2.720294 2: 36 118 8.0 72 5 2 6.000000 2.828427 3: 12 149 12.6 74 5 3 3.464102 3.549648 4: 18 313 11.5 62 5 4 4.242641 3.391165 5: NA NA 14.3 56 5 5 NA 3.781534 6: 28 NA 14.9 66 5 6 5.291503 3.860052
或作为匿名函数:
fct_those_columns(DT, old_names, new_names, function(x) x^(1/2))
head(DT)
Ozone Solar.R Wind Temp Month Day New_Ozone New_Wind 1: 41 190 7.4 67 5 1 6.403124 2.720294 2: 36 118 8.0 72 5 2 6.000000 2.828427 3: 12 149 12.6 74 5 3 3.464102 3.549648 4: 18 313 11.5 62 5 4 4.242641 3.391165 5: NA NA 14.3 56 5 5 NA 3.781534 6: 28 NA 14.9 66 5 6 5.291503 3.860052
更灵活的方法
下面的函数通过自动在输入列的名称前面加上函数的名称来派生新列的名称:
fct_those_columns <- function(DT, cols_in, fct) {
fct_name <- substitute(fct)
cols_new <- paste(if (class(fct_name) == "name") fct_name else fct_name[3], cols_in, sep = "_")
DT[, (cols_new) := lapply(.SD, fct), .SDcols = cols_in]
}
DT <- data.table(airquality)
fct_those_columns(DT, old_names, sqrt)
fct_those_columns(DT, old_names, data.table::as.IDate)
fct_those_columns(DT, old_names, function(x) x^(1/2))
DT
Ozone Solar.R Wind Temp Month Day sqrt_Ozone sqrt_Wind as.IDate_Ozone as.IDate_Wind x^(1/2)_Ozone x^(1/2)_Wind 1: 41 190 7.4 67 5 1 6.403124 2.720294 1970-02-11 1970-01-08 6.403124 2.720294 2: 36 118 8.0 72 5 2 6.000000 2.828427 1970-02-06 1970-01-09 6.000000 2.828427 3: 12 149 12.6 74 5 3 3.464102 3.549648 1970-01-13 1970-01-13 3.464102 3.549648 4: 18 313 11.5 62 5 4 4.242641 3.391165 1970-01-19 1970-01-12 4.242641 3.391165 5: NA NA 14.3 56 5 5 NA 3.781534 <NA> 1970-01-15 NA 3.781534 --- 149: 30 193 6.9 70 9 26 5.477226 2.626785 1970-01-31 1970-01-07 5.477226 2.626785 150: NA 145 13.2 77 9 27 NA 3.633180 <NA> 1970-01-14 NA 3.633180 151: 14 191 14.3 75 9 28 3.741657 3.781534 1970-01-15 1970-01-15 3.741657 3.781534 152: 18 131 8.0 76 9 29 4.242641 2.828427 1970-01-19 1970-01-09 4.242641 2.828427 153: 20 223 11.5 68 9 30 4.472136 3.391165 1970-01-21 1970-01-12 4.472136 3.391165
请注意,这x^(1/2)_Ozone
不是 R 中语法上有效的名称,需要放在反引号中:
DT$`x^(1/2)_Ozone`
推荐阅读
- laravel - 传递给 App\Http\Controllers\ApiController::showAll() 的参数 1 必须是 Illuminate\Database\Eloquent\Collection 的实例
- javascript - MongoDB:为什么评论(数组)属性上的 Array.find 返回未定义?
- tensorflow2.0 - 如何在 Tensorflow 2.0 中正确批处理 CsvDataset?
- c# - 如何使用正则表达式匹配不以某些字符开头或结尾的单词?
- mysql - 连接三个表或使用 IN 的嵌套查询
- javascript - 当我没有看到 api 结果时,我需要显示未找到数据
- c# - QuickFix/n - 登录内的自定义字段
- angular - Karma - 注入 Angular InjectionToken 问题
- c# - C# 对委托类型的泛型类型推断
- angular - Angular 等待 Promise 导致变量在模板中显示