Язык R имеет изящную функцию для определения функций, которые могут принимать переменное число аргументов. Например, функция data.frame
принимает любое количество аргументов, и каждый аргумент становится данными для столбца в результирующей таблице данных. Пример использования:
> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
letters numbers notes
1 a 1 do
2 b 2 re
3 c 3 mi
Подпись функции включает многоточие, например:
function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[FUNCTION DEFINITION HERE]
}
Я хотел бы написать функцию, которая делает нечто подобное, принимая несколько значений и объединяя их в одно возвращаемое значение (а также выполняя некоторую другую обработку). Чтобы сделать это, мне нужно выяснить, как «распаковать» ...
аргументы функции внутри функции. Я не знаю, как это сделать. Соответствующая строка в определении функции data.frame
is object <- as.list(substitute(list(...)))[-1L]
, которую я не могу понять.
Итак, как я могу преобразовать многоточие из подписи функции, например, в список?
Чтобы быть более конкретным, как я могу написать get_list_from_ellipsis
в коде ниже?
my_ellipsis_function(...) {
input_list <- get_list_from_ellipsis(...)
output_list <- lapply(X=input_list, FUN=do_something_interesting)
return(output_list)
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
редактировать
Кажется, есть два возможных способа сделать это. Они есть as.list(substitute(list(...)))[-1L]
и list(...)
. Однако эти двое не делают одно и то же. (Различия см. В примерах ответов.) Кто-нибудь может сказать мне, какова практическая разница между ними, и какую мне следует использовать?
list
иc
работа функции таким образом, но оба примитивы, так что я не могу легко проверять их исходный код , чтобы понять , как они работают.rbind.data.frame
используйте этот способ.list(...)
достаточно, почему встроенные R, например,data.frame
используютas.list(substitute(list(...)))[-1L]
вместо этого более длинную форму ?data.frame
, я не знаю ответа на этот вопрос (хотя я уверен, что для этого есть все основания). Я используюlist()
для этой цели в своих собственных пакетах и еще не столкнулся с проблемой с ним.Просто добавить к ответам Шейна и Дирка: интересно сравнить
с участием
В любом случае, любая версия кажется подходящей для ваших целей
my_ellipsis_function
, хотя первая явно проще.источник
Вы уже дали половину ответа. Рассматривать
Так что взял два аргумента
a
иb
из вызова и преобразовал его в список. Разве это не то, что вы просили?источник
[[1]]
. Кроме того, я хотел бы знать, какas.list(substitute(list(...)))
работает волшебное заклинание .list(...)
создаетlist
объект на основе аргументов. Затемsubstitute()
создает дерево разбора для неоцененного выражения; см. справку для этой функции. А также хороший продвинутый текст на R (или S). Это не тривиальные вещи.[[-1L]]
части (из моего вопроса)? Не должно ли это быть[[1]]
?print(c(1:3)[-1])
будет печатать только 2 и 3. ЭтоL
новый способ убедиться, что он заканчивается как целое число, это много сделано в источниках R.[[1]]
и$a
индексами заставила меня думать, что были задействованы вложенные списки. Но теперь я вижу, что вы на самом деле получаете список, который мне нужен, но с дополнительным элементом впереди. Так что тогда[-1L]
имеет смысл. В любом случае, откуда этот дополнительный первый элемент? И есть ли причина, по которой я должен использовать это вместо простогоlist(...)
?Это работает как ожидалось. Ниже приведен интерактивный сеанс:
То же самое, за исключением аргумента по умолчанию:
Как вы можете видеть, вы можете использовать это для передачи «дополнительных» аргументов функции внутри вашей функции, если значения по умолчанию не те, которые вы хотите в конкретном случае.
источник