Все еще пытаясь понять логику R ... каков "лучший" способ распаковать (на LHS) результаты функции, возвращающей несколько значений?
Я не могу сделать это, по-видимому:
R> functionReturningTwoValues <- function() { return(c(1, 2)) }
R> functionReturningTwoValues()
[1] 1 2
R> a, b <- functionReturningTwoValues()
Error: unexpected ',' in "a,"
R> c(a, b) <- functionReturningTwoValues()
Error in c(a, b) <- functionReturningTwoValues() : object 'a' not found
я действительно должен сделать следующее?
R> r <- functionReturningTwoValues()
R> a <- r[1]; b <- r[2]
или программист на R напишет что-то вроде этого:
R> functionReturningTwoValues <- function() {return(list(first=1, second=2))}
R> r <- functionReturningTwoValues()
R> r$first
[1] 1
R> r$second
[1] 2
--- отредактировано, чтобы ответить на вопросы Шейна ---
Мне не нужно давать имена частям значений результата. Я применяю одну агрегатную функцию к первому компоненту, а другую - ко второму компоненту ( min
и max
. Если бы это была одна и та же функция для обоих компонентов, мне не нужно было бы их разбивать).
attr
возвращаемое значение.Ответы:
(1) list [...] <- я разместил это более десяти лет назад на r-help . С тех пор он был добавлен в пакет gsubfn. Это не требует специального оператора, но требует, чтобы левая часть была написана
list[...]
следующим образом:Если вам нужен только первый или второй компонент, все это тоже работает:
(Конечно, если вам нужно только одно значение, то
functionReturningTwoValues()[[1]]
илиfunctionReturningTwoValues()[[2]]
будет достаточно.)Смотрите процитированную ветку r-help для большего количества примеров.
(2) с Если намерение состоит в том, чтобы просто объединить несколько значений последовательно, а возвращаемые значения именуются, то простой альтернативой является использование
with
:(3) прикрепить Другой альтернативой является прикрепление:
ДОБАВЛЕНО:
with
иattach
источник
list
и[<-.result
как показано там?Я каким-то образом наткнулся на этот хитрый взлом в Интернете ... Я не уверен, что это противно или красиво, но он позволяет вам создать "магический" оператор, который позволяет вам распаковать несколько возвращаемых значений в их собственную переменную.
:=
Функция определена здесь , и приводится ниже для потомков:Имея это в виду, вы можете делать то, что вам нужно:
Я не знаю, что я чувствую по этому поводу. Возможно, вы найдете это полезным в вашем интерактивном рабочем пространстве. Использование его для создания (повторного) использования библиотек (для массового потребления) может быть не самой лучшей идеей, но я думаю, это ваше дело.
... вы знаете, что они говорят об ответственности и власти ...
источник
:=
оператор mucho более удобным способом :-)Обычно я заключаю вывод в список, который очень гибок (вы можете иметь любую комбинацию чисел, строк, векторов, матриц, массивов, списков, объектов в выводе)
так как:
источник
Я думаю, что это работает.
источник
Я собрал пакет R Zeallot для решения этой проблемы. Zeallot включает в себя оператор множественного присваивания или распаковки присваивания
%<-%
. LHS оператора - это любое количество переменных для назначения, построенных с использованием вызововc()
. RHS оператора - это вектор, список, фрейм данных, объект даты или любой пользовательский объект с реализованнымdestructure
методом (см.?zeallot::destructure
).Вот несколько примеров, основанных на оригинальном посте:
Проверьте виньетка пакета для получения дополнительной информации и примеров.
источник
Там нет правильного ответа на этот вопрос. Я действительно зависит от того, что вы делаете с данными. В приведенном выше простом примере я настоятельно рекомендую:
Важно ли, чтобы значения 1 и 2 выше имели имена? Другими словами, почему в этом примере важно, чтобы 1 и 2 были названы a и b, а не просто r [1] и r [2]? В этом контексте важно понимать, что a и b также являются векторами длины 1. Таким образом, вы ничего не меняете в процессе выполнения этого назначения, кроме двух новых векторов, которым не нужны индексы для быть ссылки:
Вы также можете присвоить имена исходному вектору, если вы предпочитаете ссылаться на букву, а не на индекс:
[Править] Учитывая, что вы будете применять минимальное и максимальное значения к каждому вектору в отдельности, я бы предложил использовать либо матрицу (если a и b будут одинаковой длины и одинакового типа данных), либо фрейм данных (если a и b будут одинаковой длины, но могут быть разных типов данных) или использовать список, как в вашем последнем примере (если они могут иметь различную длину и типы данных).
источник
r[1]
может помочь сделать вещи более ясными (хорошо, если имена неa
приходят на их место).Списки кажутся идеальными для этой цели. Например, в функции, которую вы бы имели
основная программа
источник
Да, на ваш второй и третий вопросы - это то, что вам нужно сделать, так как вы не можете иметь несколько «lvalues» слева от задания.
источник
Как насчет использования assign?
Вы можете передать имена переменных, которые вы хотите передать по ссылке.
Если вам нужно получить доступ к существующим значениям, обратное утверждение
assign
- этоget
.источник
r <- function() { return(list(first=1, second=2)) }
и ссылаться на результаты, используяr$first
иr$second
.Если вы хотите вернуть выходные данные своей функции в глобальную среду, вы можете использовать
list2env
, как в этом примере:Эта функция создаст три объекта в вашей глобальной среде:
источник
[A] Если каждый из foo и bar представляет собой одно число, то в c нет ничего плохого (foo, bar); и вы также можете назвать компоненты: c (Foo = foo, Bar = bar). Таким образом, вы можете получить доступ к компонентам результата 'res' как res [1], res [2]; или, в именованном случае, как res ["Foo"], res ["BAR"].
[B] Если foo и bar являются векторами одного типа и длины, то опять же нет ничего плохого в возврате cbind (foo, bar) или rbind (foo, bar); также можно назвать В случае 'cbind' вы можете получить доступ к foo и bar как res [, 1], res [, 2] или как res [, "Foo"], res [, "Bar"]. Вы также можете предпочесть вернуть фрейм данных, а не матрицу:
и получить к ним доступ как res $ Foo, res $ Bar. Это также будет хорошо работать, если foo и bar имеют одинаковую длину, но не одного типа (например, foo - это вектор чисел, а bar - вектор символьных строк).
[C] Если foo и bar достаточно разные, чтобы их не было удобно комбинировать, как указано выше, тогда вы обязательно должны вернуть список.
Например, ваша функция может соответствовать линейной модели, а также вычислять прогнозные значения, чтобы вы могли иметь
и тогда вы бы
return list(Foo=foo,Bar=bar)
и затем получить доступ к сводке как Res $ Foo, прогнозируемые значения как Res $ Barисточник: http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html
источник
Чтобы получить несколько выходных данных из функции и сохранить их в нужном формате, вы можете сохранить выходные данные на жестком диске (в рабочем каталоге) изнутри функции, а затем загрузить их извне функции:
источник
С R 3.6.1 я могу сделать следующее
источник