Dplyr join on by = (a = b), где a и b - переменные, содержащие строки?

Я пытаюсь выполнить внутреннее объединение двух таблиц с использованием dplyr, и я думаю, что меня нарушают нестандартные правила оценки. При использовании аргумента by = ( "a" = "b" ) все работает так, как ожидалось, когда "a" и "b" являются фактическими строками. Здесь показан пример с игрушкой:

library(dplyr)
data(iris)

inner_join(iris, iris, by=c("Sepal.Length" = "Sepal.Width"))

Но скажем, я помещал функцию inner_join в функцию:

library(dplyr)
data(iris)

myfn <- function(xname, yname) {
    data(iris)
    inner_join(iris, iris, by=c(xname = yname))
}

myfn("Sepal.Length", "Sepal.Width")

Это возвращает следующую ошибку:

Error: cannot join on columns 'xname' x 'Sepal.Width': index out of bounds

Я подозреваю, что есть какое-то причудливое выражение, deparsing, quoting или unquoting, что я мог бы сделать, чтобы сделать эту работу, но я немного мрачен в этих деталях.

Ответы

Ответ 1

Вы можете использовать

myfn <- function(xname, yname) {
    data(iris)
    inner_join(iris, iris, by=setNames(yname, xname))
}

Предлагаемый синтаксис в документации ?inner_join

by = c("a"="b")   # same as by = c(a="b")

немного вводит в заблуждение, поскольку оба эти значения не являются надлежащими значениями символов. Фактически вы создали именованный символьный вектор. Для динамического задания значений слева от знака равенства отличается от значений справа. Вы можете использовать setNames() для динамического определения имен вектора.

Ответ 2

Я знаю, что опаздываю на вечеринку, но как насчет:

myfn <- function(byvar) {
  data(iris)
  inner_join(iris, iris, by=byvar)
}

Таким образом вы можете делать то, что хотите:

myfn(c("Sepal.Length"="Sepal.Width"))