【发布时间】:2021-08-18 19:58:27
【问题描述】:
这是一个令我困惑的问题。编写函数以在返回多个向量的变异部分中使用的最简单(也是最优雅)的方法是什么。
我举个例子。假设我有这样的功能。
f1 = function(x, n){
y1 = rep(NA, length(x))
y2 = rep(NA, length(x))
y3 = rep(NA, length(x))
y4 = rep(NA, length(x))
for(i in (n+1):(length(x)-n)){
idx = (i-n):(i+n)
y1[i] = sin(mean(x[idx])/max(x[idx]))
y2[i] = cos(mean(x[idx])/max(x[idx]))
y3[i] = tan(mean(x[idx])/max(x[idx]))
y4[i] = 1/tan(mean(x[idx])/max(x[idx]))
}
data.frame(
y1 = y1,
y2 = y2,
y3 = y3,
y4 = y4
)
}
请不要分析它的数学意义,这只是一个例子。 如您所见,此函数接受一个向量并返回四个相同长度的向量。 如果我想在突变部分使用这个函数,该函数将被调用四次。不幸的是,输入向量很长,需要很长时间。
这是一个例子。
n = 10000
df = tibble(
key = rep(c("a", "b", "c", "d"), n),
val = rep(rnorm(n), 4)
)
f1test = function(df) df %>%
group_by(key) %>%
mutate(
y1 = f1(val, 100) %>% pull(y1),
y2 = f1(val, 100) %>% pull(y2),
y3 = f1(val, 100) %>% pull(y3),
y4 = f1(val, 100) %>% pull(y4)
)
f1test(df)
在寻找解决方案时,我有一个稍微不同的想法,即一次返回所有四个向量,然后以某种方式将它们分开。 所以我创建了第二个示例函数,它执行相同的计算,只是返回结果的方式不同。
f2 = function(x, n){
ret = rep(NA, length(x))
for(i in (n+1):(length(x)-n)){
idx = (i-n):(i+n)
ret[i] = paste(
sin(mean(x[idx])/max(x[idx])),
cos(mean(x[idx])/max(x[idx])),
tan(mean(x[idx])/max(x[idx])),
1/tan(mean(x[idx])/max(x[idx])), sep = ";")
}
ret
}
使用此类函数可能如下所示:
f2test = function(df) df %>%
group_by(key) %>%
mutate(ret = f2(val, 100)) %>%
separate(ret, paste0("y", 1:4), sep=";", convert = TRUE)
f2test(df)
您可以立即看到后者应该更快。确实是 n = 1000,f2 的版本大约快 2 倍。
对于 n = 10000,它快四倍。
现在我的问题。有谁知道更好(更优雅)的方法来解决这个问题?
【问题讨论】: