如何将 dplyr 中的动态列名传递给自定义函数?

How to pass dynamic column names in dplyr into custom function?

我有一个具有以下结构的数据集:

Classes ‘tbl_df’ and 'data.frame':  10 obs. of  7 variables:
 $ GdeName  : chr  "Aeugst am Albis" "Aeugst am Albis" "Aeugst am Albis" "Aeugst am Albis" ...
 $ Partei   : chr  "BDP" "CSP" "CVP" "EDU" ...
 $ Stand1971: num  NA NA 4.91 NA 3.21 ...
 $ Stand1975: num  NA NA 5.389 0.438 4.536 ...
 $ Stand1979: num  NA NA 6.2774 0.0195 3.4355 ...
 $ Stand1983: num  NA NA 4.66 1.41 3.76 ...
 $ Stand1987: num  NA NA 3.48 1.65 5.75 ...

我想提供一个允许计算任何值之间的差异的函数,我想使用 dplyrs mutate 函数来做到这一点:(假设参数 fromto 作为参数传递)

from <- "Stand1971"
to <- "Stand1987"

data %>%
  mutate(diff = from - to)

当然,这是行不通的,因为dplyr使用了非标准评估。我知道现在有一个使用 mutate_ 来解决问题的优雅解决方案,而且我已经阅读了 this vignette,但我仍然无法理解它。

怎么办?

这是可重现示例的数据集的前几行

structure(list(GdeName = c("Aeugst am Albis", "Aeugst am Albis", 
"Aeugst am Albis", "Aeugst am Albis", "Aeugst am Albis", "Aeugst am Albis", 
"Aeugst am Albis", "Aeugst am Albis", "Aeugst am Albis", "Aeugst am Albis"
), Partei = c("BDP", "CSP", "CVP", "EDU", "EVP", "FDP", "FGA", 
"FPS", "GLP", "GPS"), Stand1971 = c(NA, NA, 4.907306434, NA, 
3.2109535926, 18.272143463, NA, NA, NA, NA), Stand1975 = c(NA, 
NA, 5.389079711, 0.4382328556, 4.5363022622, 18.749259742, NA, 
NA, NA, NA), Stand1979 = c(NA, NA, 6.2773722628, 0.0194647202, 
3.4355231144, 25.294403893, NA, NA, NA, 2.7055961071), Stand1983 = c(NA, 
NA, 4.6609804428, 1.412940467, 3.7563539244, 26.277246489, 0.8529335746, 
NA, NA, 2.601878177), Stand1987 = c(NA, NA, 3.4767860929, 1.6535933856, 
5.7451770193, 22.146844746, NA, 3.7453183521, NA, 13.702211858
)), .Names = c("GdeName", "Partei", "Stand1971", "Stand1975", 
"Stand1979", "Stand1983", "Stand1987"), class = c("tbl_df", "data.frame"
), row.names = c(NA, -10L))

使用最新版本的dplyr(>=0.7),可以使用rlang !! (bang-bang)运算符。

library(tidyverse)
from <- "Stand1971"
to <- "Stand1987"

data %>%
  mutate(diff=(!!as.name(from))-(!!as.name(to)))

您只需要将字符串转换为带有 as.name 的名称,然后将它们插入到表达式中。不幸的是,我似乎不得不使用比我想要的更多的括号,但是 !! 运算符似乎属于一个奇怪的操作顺序。

原答案,dplyr (0.3-<0.7):

从那个小插图 (vignette("nse","dplyr")) 开始,使用 lazyeval 的 interp() 函数

library(lazyeval)

from <- "Stand1971"
to <- "Stand1987"

data %>%
  mutate_(diff=interp(~from - to, from=as.name(from), to=as.name(to)))

您现在可以在 dplyr 链中使用 .data

library(dplyr)
from <- "Stand1971"
to <- "Stand1987"

data %>% mutate(diff = .data[[from]] - .data[[to]])

另一种选择是使用 sym 和 bang-bang (!!)

data %>% mutate(diff = !!sym(from) - !!sym(to))

在基础 R 中,我们可以使用:

data$diff <- data[[from]] - data[[to]]