问题简述:我编写了一个自定义函数来计算变量年度百分比变化。我想使用purrr的map_at函数将我的自定义函数应用于变量名称向量。当我将自定义函数应用于单个变量时,它可以正常工作,但在使用map_a链接时失败。
我的自定义函数如下:
calculate_delta <- function(df, col) {
#generate variable name
newcolname = paste("d", col, sep="")
#get formula for first difference.
calculate_diff <- lazyeval::interp(~(a + lag(a))/a, a = as.name(col))
#pass formula to mutate, name new variable the columname generated above
df %>%
mutate_(.dots = setNames(list(calculate_diff), newcolname)) }
当我将此函数应用于mtcars数据集中的单个变量时,输出结果如预期所示(尽管显然结果的含义是无意义的)。
calculate_delta(mtcars, "wt")
尝试使用Purrr将函数应用于字符向量
我认为我在理解map_at如何传递参数给函数方面遇到了困难。我在网上找到的所有示例片段都使用像is.character
这样不需要其他参数的函数进行map_at操作。以下是我尝试使用purrr
应用函数的方法。
vars <- c("wt", "mpg")
mtcars %>% map_at(vars, calculate_delta)
这给我返回了以下错误信息:
Error in paste("d", col, sep = "") : argument "col" is missing, with no default
我猜测这是因为map_at将vars
作为df
传递,但没有传递col
参数。为了解决这个问题,我尝试了以下方法:
vars <- c("wt", "mpg")
mtcars %>% map_at(vars, calculate_delta, df = .)
这让我出现了这个错误:
Error: unrecognised index type
我已经尝试了很多不同版本,包括从calculate_delta
函数中删除df
参数,但是都没有成功。
其他可能的解决方案
1)使用sapply
而不是purrr
的版本。 我尝试过这种方法来解决问题,但是遇到了类似的问题。我的目标是找出一种使用purrr的方法,如果可能的话。 根据我对purrr
的理解,这似乎是一个典型的用例。
2)显然,我可以想到如何使用for循环来实现这一点,但是出于类似的原因,我正在尽可能避免这样做。
显然,我的思考方式是错误的。 请帮忙!
编辑1
为了澄清,我想知道是否有一种重复转换变量的方法,可以完成以下两件事情。
1)在原始的tbl_df
中生成新变量,而不替换被突变的列(就像使用dplyr
的mutate_at
时所发生的那样)。
2)自动生成新的变量标签。
3)如果可能的话,通过使用map_at
应用单个函数来完成我所描述的内容。
可能这是不可能的,但我觉得应该有一种优雅的方法来实现我所描述的内容。
mutate
或类似的结构中。尝试mtcars %>% mutate(calculate_delta(wt))
,即使没有purrr
或map
,它也无法工作。如果在普通的dplyr
调用中无法工作,则在该结构中也无法工作。它应该被重新编写。可以从删除数据框规范的必要性开始。考虑一下sum
或mean
不需要数据框作为调用的一部分,它们是为向量构建的。 - Pierre Ldelta <- function(x) (x + dplyr::lag(x)) /x
,它也可以与purrr
一起使用。正如我在下面提到的,让我困扰的部分是动态地重命名变量。 - Sean Williams