Język R ma ciekawą funkcję do definiowania funkcji, które mogą przyjmować zmienną liczbę argumentów. Na przykład funkcja data.frame
przyjmuje dowolną liczbę argumentów, a każdy argument staje się danymi dla kolumny w wynikowej tabeli danych. Przykładowe użycie:
> 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
Podpis funkcji zawiera wielokropek, taki jak ten:
function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[FUNCTION DEFINITION HERE]
}
Chciałbym napisać funkcję, która robi coś podobnego, biorąc wiele wartości i konsolidując je w jedną wartość zwracaną (a także wykonując inne przetwarzanie). Aby to zrobić, muszę dowiedzieć się, jak „rozpakować” ...
argumenty funkcji w funkcji. Nie wiem jak to zrobić. Odpowiednią linią w definicji funkcji data.frame
jest object <- as.list(substitute(list(...)))[-1L]
, której nie rozumiem.
Jak mogę przekonwertować wielokropek z podpisu funkcji na, na przykład, listę?
Mówiąc ściślej, jak mogę napisać get_list_from_ellipsis
w poniższym kodzie?
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)
Edytować
Wydaje się, że istnieją dwa możliwe sposoby, aby to zrobić. Oni są as.list(substitute(list(...)))[-1L]
i list(...)
. Jednak ci dwaj nie robią dokładnie tego samego. (Aby zapoznać się z różnicami, zobacz przykłady w odpowiedziach.) Czy ktoś może mi powiedzieć, jaka jest praktyczna różnica między nimi, a której powinienem użyć?
list
ic
działają w ten sposób, ale obie są prymitywami, więc nie mogę łatwo sprawdzić ich kodu źródłowego, aby zrozumieć, jak działają.rbind.data.frame
użyj tego sposobu.list(...)
jest wystarczające, dlaczego wbudowane R, takie jak zamiast tegodata.frame
używają dłuższej formyas.list(substitute(list(...)))[-1L]
?data.frame
, nie znam odpowiedzi na to pytanie (który powiedział, jestem pewien, że nie jest to dobry powód, dla niego). Używamlist()
do tego celu w swoich własnych pakietach i jeszcze nie mam z tym problemu.Wystarczy dodać do odpowiedzi Shane'a i Dirka: interesujące jest porównanie
z
W tej chwili każda z wersji wydaje się odpowiednia do twoich celów
my_ellipsis_function
, choć pierwsza jest wyraźnie prostsza.źródło
Dałeś już połowę odpowiedzi. Rozważać
Wzięło to dwa argumenty
a
ib
wywołanie i przekonwertowało je na listę. Czy nie o to prosiłeś?źródło
[[1]]
. Chciałbym również wiedzieć, jak działa magiczna inkantacjaas.list(substitute(list(...)))
.list(...)
tworzylist
obiekt na podstawie argumentów. Następniesubstitute()
tworzy drzewo analizy dla nieocenionego wyrażenia; zobacz pomoc dotyczącą tej funkcji. Jak również dobry zaawansowany tekst na R (lub S). To nie jest banalne.[[-1L]]
częścią (z mojego pytania)? Nie powinno tak być[[1]]
?print(c(1:3)[-1])
Wydrukuje tylko 2 i 3.L
Jest nowy-fangled sposób, aby zapewnić, że kończy się jako liczbę całkowitą, odbywa się to dużo w źródłach R.[[1]]
a$a
wskaźnikami sprawiła, że pomyślałem, że w grę wchodziły zagnieżdżone listy. Ale teraz widzę, że tak naprawdę to lista, której chcę, ale z dodatkowym elementem z przodu. Więc to[-1L]
ma sens. Skąd w ogóle pochodzi ten dodatkowy pierwszy element? Czy jest jakiś powód, dla którego powinienem używać tego zamiast po prostulist(...)
?Działa to zgodnie z oczekiwaniami. Oto sesja interaktywna:
To samo, z wyjątkiem domyślnego argumentu:
Jak widać, możesz użyć tego do przekazania „dodatkowych” argumentów do funkcji w obrębie funkcji, jeśli wartości domyślne nie są takie, jakie chcesz w konkretnym przypadku.
źródło