Передайте data.frame имя столбца функции

Я пытаюсь записать функцию для принятия data.frame (x) и a column от него. Функция выполняет некоторые вычисления на x и более поздние возвраты другой data.frame. Я застреваю на методе лучших практик для передачи имени столбца функции.

Два минимальных примера fun1 и fun2 ниже приводят к желаемому результату, способность выполнить операции на x$column, использование max() как пример. Однако оба полагаются по-видимому (по крайней мере, мне) неэлегантный

  1. звоните в substitute() и возможно eval()
  2. потребность передать имя столбца как символьный вектор.

fun1 <- function(x, column){
  do.call("max", list(substitute(x[a], list(a = column))))
}

fun2 <- function(x, column){
  max(eval((substitute(x[a], list(a = column)))))
}

df <- data.frame(B = rnorm(10))
fun1(df, "B")
fun2(df, "B")

Я хотел бы смочь вызвать функцию как fun(df, B), например. Другие опции я рассмотрел, но не попробовал:

  • Передача column как целое число номера столбца. Я думаю, что это избежало бы substitute(). Идеально, функция могла принять также.
  • with(x, get(column)), но, даже если бы это работает, я думаю, что это все еще потребовало бы substitute
  • Использовать formula() и match.call(), ни один из которых у меня есть много опыта с.

Дополнительный вопрос: do.call() предпочтенный eval()?

105
задан Bhargav Rao 15 March 2016 в 14:37
поделиться

2 ответа

Вы можете просто использовать имя столбца напрямую:

df <- data.frame(A=1:10, B=2:11, C=3:12)
fun1 <- function(x, column){
  max(x[,column])
}
fun1(df, "B")
fun1(df, c("B","A"))

Нет необходимости использовать замену, eval и т. Д.

Вы даже можете передать желаемое функция как параметр:

fun1 <- function(x, column, fn) {
  fn(x[,column])
}
fun1(df, "B", max)

В качестве альтернативы, использование [[ также работает для выбора одного столбца за раз:

df <- data.frame(A=1:10, B=2:11, C=3:12)
fun1 <- function(x, column){
  max(x[[column]])
}
fun1(df, "B")
92
ответ дан 24 November 2019 в 04:00
поделиться

Лично я считаю, что передавать столбец в виде строки довольно некрасиво. Мне нравится делать что-то вроде:

get.max <- function(column,data=NULL){
    column<-eval(substitute(column),data, parent.frame())
    max(column)
}

, что даст:

> get.max(mpg,mtcars)
[1] 33.9
> get.max(c(1,2,3,4,5))
[1] 5

Обратите внимание, что спецификация data.frame является необязательной. вы даже можете работать с функциями ваших столбцов:

> get.max(1/mpg,mtcars)
[1] 0.09615385
22
ответ дан 24 November 2019 в 04:00
поделиться