Как использовать с / внутри функции? - PullRequest
7 голосов
/ 19 мая 2011

Я изо всех сил пытаюсь понять, почему это не работает.

df <- data.frame(a=1:10, b=1:10)

foo <- function(obj, col) {
   with(obj, ls())
   with(obj, print(col))
}
foo(df, a)

[1] "a" "b"

Ошибка печати (столбец): объект 'a' не найден

Если это работает:

with(df, print(a))

Ответы [ 3 ]

12 голосов
/ 19 мая 2011

with удобен и улучшает читаемость в интерактивном контексте, но может повредить ваш мозг в контексте программирования, когда вы передаете вещи назад и вперед функциям и работаете с вещами в различных средах.В целом, в R использование символов, а не имен, является своего рода «семантическим сахаром», который удобен и удобен для чтения в интерактивном режиме, но слегка не рекомендуется для программирования [например, $, subset]).Если вы готовы пойти на компромисс, если будете использовать имя ("a"), а не символ (a), тогда я бы предложил вернуться к более простому obj[[col]] вместо использования with здесь ...

Итак, как самостоятельный ответ:

foo <- function(object,col) {
   print(names(object))
   print(object[[col]])
}

Если вы хотите разрешить несколько столбцов (то есть вектор символов)

foo <- function(object,col) {
   print(names(object))
   print(object[col])
}

edit: отказ от использования subset с функцией по предложению @ hadley

(при этом ответ печатается в виде фрейма данных, даже если выбран один столбец, что может оказаться не тем, что вам нужно).

4 голосов
/ 19 мая 2011

Все, что передается в функцию, должно быть объектом, строкой или числом. Есть две проблемы с этим:

  1. В этом случае вы пытаетесь передать «а» как объект, когда вы действительно должны передавать его как строку.
  2. с (obj, ls ())) вернется к среде функций (область видимости функций), а не к экрану, если вы не скажете ему напечатать.

То, что вы хотите, больше похоже на:

foo <- function(obj, col) {
       print(with(obj, ls()))
       with(obj, print(obj[[col]]))
    }

foo(df, "a")

Или, если вы ищете только один столбец для печати:

foo <- function(obj, col) {
           with(obj, print(obj[[col]]))
        }

foo(df, "a")
1 голос
/ 19 мая 2011

В аргументе функции col оценивается перед использованием в функции с (что противоположно интерактивному использованию). Здесь у вас есть два решения этой проблемы.

foo1 <- function(obj, col) {
          with(obj, print(eval(col)))
        }
foo1(mydf, quote(a))# here you have to remember to quote argument


foo2 <- function(obj, col) {
          col <- as.expression(as.name(substitute(col)))#corrected after DWIN comment
          with(obj, print(eval(col)))
        }
foo2(mydf, a)# this function does all necessary stuff
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...