Передача аргументов функциям и областей видимости переменных в R

Я пишу простую функцию, которая принимает два аргумента (состояние, результат). Состояние используется для подмножества фрейма данных позже.

Сказав это, часть требования состоит в том, чтобы состояние было вектором символов длиной 2. Мне нужно написать больше кода, чтобы гарантировать, что переданное состояние соответствует этому требованию.

Итак, я написал следующее:

best <- function(state, outcome) {

  outcome <- read.csv("outcome-of-care-measures.csv", colClasses = "character")
  state <- vector(mode = "character", length = 2)
  st.checkTbl <- outcome[8]

  state
  }

Однако, когда я вызываю функцию и передаю аргументы:

best("AXA") or best("FOO") or even best("TX") or best(AL)

Все, что я возвращаю, это: "" ""

Если я закомментирую #state ‹- ... тогда аргумент передается нормально и выводится« FOO »,« AXA »,« TX »и т. Д.

Как я могу гарантировать, что аргумент, переданный функции, сохранен как переменная (состояние) в функции? Или я слишком много думаю об этом? На самом деле я просто хотел проверить, что то, что я передаю аргументу состояния, можно распечатать в тестовых целях.

. Простите за 101 урок.


person Zach    schedule 24.03.2015    source источник
comment
Похоже, вы над этим слишком много думаете. Кроме того, не совсем ясно, что эта функция должна делать, поскольку все, что она вернет, - это пустой вектор символов или, если вы закомментировали строку, исходное значение, которое вы указали для state. Возможно, вы захотите предоставить для написания своих собственных функций раздел Введение в руководство по R.   -  person Thomas    schedule 25.03.2015
comment
Независимо от того, что вы указали для состояния, вы переопределите его с помощью state <- vector(...) внутри функции   -  person Rich Scriven    schedule 25.03.2015
comment
Томас, я думаю, ты прав. Я слишком много думаю о том, что R просто знает, что делать с моим аргументом состояния. Я пытаюсь выяснить, как он знает, куда отправить значение состояния, и доказываю себе, что на самом деле он делает то, что я хочу.   -  person Zach    schedule 25.03.2015
comment
@RichardScriven Я понял это, подумав об этом в течение минуты, поэтому я получил пустой вектор символов. Спасибо!   -  person Zach    schedule 25.03.2015
comment
Вы можете взглянуть на свои аргументы, например, f <- function(x) as.list(match.call()[-1]); f("hello") и вы видите, что x был введен как привет   -  person Rich Scriven    schedule 25.03.2015
comment
Вы также можете отлаживать свою функцию с помощью debug(best) и просматривать все значения объектов внутри выполнения вашей функции.   -  person Thomas    schedule 25.03.2015
comment
Отлично. Но как мне точно узнать, где R хранит его, и что он знает, что с ним делать? Итак, если я скажу лучше (Техас) и использую какой-то псевдокод [посмотрите на состояние и посмотрите, находится ли это состояние в этой таблице состояний], R неявно знает, что, когда я говорю, посмотрите на состояние, это состояние из моего аргумента функции, а не другое государство? Я предполагаю, что это связано с тем, что состояние функции является частью глобальной среды, а поскольку не определено (как только я удаляю назначение в функции) в функции, которую он ищет и находит? - пора перечитать обзор!   -  person Zach    schedule 25.03.2015
comment
Вот некоторые рекомендуемые материалы для чтения: cran.r-project.org /doc/contrib/Fox-Companion/appendix-scope.pdf, stackoverflow.com/questions/1169534/, adv-r.had.co.nz/Functions.html#lexical-scoping   -  person Thomas    schedule 25.03.2015


Ответы (1)


Обычно вы читаете свои данные вне какой-либо функции, например:

outcome.data <- read.csv("outcome-of-care-measures.csv", colClasses = "character")

В противном случае, поскольку функция имеет свой собственный namespace, все переменные, определенные внутри нее, исчезнут при ее возврате, если только они сами не будут возвращены функцией с return(...). Несколько объектов можно вернуть, поместив их в список: return(list(item1=var1, item2=var2)).

Некоторые функции, такие как assign, имеют параметр envir, для которого можно задать значение .GlobalEnv, чтобы изменить это поведение. Изменение объекта также можно выполнить внутри функции с помощью оператора <<- вместо <-, хотя такая практика обычно не рекомендуется.

В качестве примечания, при использовании функции вам необходимо четко определить:

  1. Каковы его входы
  2. Что оно делает
  3. Что это возвращает

Например, бесполезно использовать outcome в качестве параметра функции, а затем считывать в переменную с именем income содержимое файла csv. Тогда ваш аргумент будет бесполезен, так как он будет переписан. Вот почему вам пришлось закомментировать строку, определяющую вашу переменную state внутри функции, чтобы действительно иметь возможность использовать state в том виде, в котором она была получена функцией.

Конечно, это не ответит на все ваши вопросы, но, надеюсь, поможет вам прояснить некоторые вещи. В остальном есть много хороших руководств, чтобы узнать, как программировать на R и как / когда использовать функции. Удачи и приятного обучения!

person Dominic Comtois    schedule 24.03.2015
comment
Хотя этот совет и полезен, я не думаю, что этот совет отвечает на главный вопрос OP, который касается области видимости переменных. - person Thomas; 25.03.2015
comment
Ты прав. Я добавил небольшое объяснение по этому поводу. Надеюсь, OP сочтет это полезным, даже если не полностью удовлетворительным, в качестве ответа. - person Dominic Comtois; 25.03.2015
comment
Отличная помощь, хотя @DominicComtois, и я очень признателен. Мне очень нравится R, и я учусь любить все эти научные данные! Итак, вы бы порекомендовали функцию, которая считывает все мои данные и затем передает эти переменные функции, которая их обрабатывает? - person Zach; 25.03.2015
comment
@Zach Для чтения данных обычно это делается вне функции. Если у вас есть много файлов для чтения, вы можете, например, написать цикл, который поместит все фреймы данных (созданные read.csv или read.table) в список. Тогда да, использование функции или нескольких функций может быть хорошей идеей для некоторой обработки. Но основная работа может быть в GlobalEnv (вне какой-либо функции), и тогда вам может потребоваться написать несколько небольших функций, которые делают определенные вещи. Решение, когда стоит писать функцию или нет, приходит с практикой. Обычно это способ избежать повторения, но это не ЕДИНСТВЕННЫЙ способ! - person Dominic Comtois; 25.03.2015