Подтвердить что ты не робот

Как передать динамические имена столбцов в dplyr в пользовательскую функцию?

У меня есть набор данных со следующей структурой:

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 ...

Я хочу предоставить функцию, которая позволяет вычислить разницу между любым значением, и я хотел бы сделать это с помощью функции dplyr mutate, например: (предположим, что переданы параметры from и to как аргументы)

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

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

Конечно, это не работает, поскольку dplyr использует нестандартную оценку. И я знаю, что теперь есть элегантное решение проблемы с помощью mutate_, и я прочитал эту виньетку, но я все еще не могу обдумать ее.

Что делать?

Здесь первые несколько строк набора данных для воспроизводимого примера

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))
4b9b3361

Ответ 1

Используя последнюю версию 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)))

Ответ 2

Почему бы не просто paste?

data %>%
  mutate_(diff = paste(from, "-", to))