我正在尝试使用mutate_()创建多个列,其中每个列都基于使用不同输入调用的自定义函数。我可以使用paste()创建多个带引号的函数调用,但这不起作用,因为dplyr的NSE需要公式(〜)而不是引用的字符串才能找到该函数。如何写下面的“dots =”行,以便找到该功能?我尝试使用〜,as.formula()和lazyeval :: interp()进行实验,但无法使用任何工作。我的实际“前缀”是一个长向量,所以我不想单独写出每个新列的函数调用。感谢
library(dplyr)
library(lazyeval)
library(nycflights13)
myfunc = function(x, y) { x - y }
# this works
flights1 <- mutate(flights, dep_time_sched = myfunc(dep_time, dep_delay),
arr_time_sched = myfunc(arr_time, arr_delay))
# this doesn't - Error: could not find function "myfunc"
prefixes <- c('dep', 'arr')
dots = as.list(paste0('myfunc(',
paste0(prefixes, '_time'), ', ',
paste0(prefixes, '_delay)')))
flights2 <- mutate_(flights, .dots = setNames(dots, paste0(prefixes, '_time_sched')))
答案 0 :(得分:5)
您可以使用interp
和lapply
来循环搜索前缀并获取mutate_
所需格式的列表。
dots = lapply(prefixes, function(var) interp(~myfunc(x, y),
.values = list(x = as.name(paste0(var, "_time")),
y = as.name(paste0(var, "_delay")))))
dots
[[1]]
~myfunc(dep_time, dep_delay)
<environment: 0x0000000019e51f00>
[[2]]
~myfunc(arr_time, arr_delay)
<environment: 0x0000000019f1e5b0>
这会产生与flights1
相同的结果。
flights2 = mutate_(flights, .dots = setNames(dots, paste0(prefixes, '_time_sched')))
identical(flights1, flights2)
[1] TRUE
答案 1 :(得分:3)
我的实际&#34;前缀&#34;是一个长向量,所以我不想单独写出每个新列的函数调用。
如果是这种情况,您应该真正将数据转换为长格式。为了澄清我的意思,让我们看一个较小的例子:
mydat <- flights[1:5, c(paste0(prefixes,"_time"), paste0(prefixes,"_delay"))]
# dep_time arr_time dep_delay arr_delay
# (int) (int) (dbl) (dbl)
# 1 517 830 2 11
# 2 533 850 4 20
# 3 542 923 2 33
# 4 544 1004 -1 -18
# 5 554 812 -6 -25
library(data.table)
longdat <- setDT(mydat)[, .(
pref = rep(prefixes, each=.N),
time = unlist(mget(paste0(prefixes,"_time"))),
delay = unlist(mget(paste0(prefixes,"_delay")))
)]
longdat[, time_sched := myfunc(time, delay) ]
# pref time delay time_sched
# 1: dep_ 517 2 515
# 2: dep_ 533 4 529
# 3: dep_ 542 2 540
# 4: dep_ 544 -1 545
# 5: dep_ 554 -6 560
# 6: arr_ 830 11 819
# 7: arr_ 850 20 830
# 8: arr_ 923 33 890
# 9: arr_ 1004 -18 1022
# 10: arr_ 812 -25 837
除了更简单之外,一次调用函数可以利用它的向量化。
虽然我使用data.table构建longdat
,但我确定有一个工具可以在tidyr包中执行相同的操作(与dplyr配套)。同样,添加time_sched
列只是mutate
。
重塑的其他方式感谢@akrun,这是使用longdat
函数语法转到melt
的另一种方法,该语法将在下一版本的数据中提供.table(1.9.8,尚未发布):
longdat <- melt(mydat,
measure = patterns('time$','delay$'),
variable.name = "pref",
value.name = c('time', 'delay')
)[, pref := prefixes[pref]]
或者,也感谢@akrun,这里有一种重塑的方法,在给定后缀(time
和delay
)的情况下使用@ AnandaMahto的splitstackshape包自动构造前缀:
library(splitstackshape)
longdat <- merged.stack(transform(mydat, ind=1:nrow(mydat)),
var.stubs = c('_time', '_delay'),
sep = 'var.stubs',
atStart = FALSE)