Wciąż próbuję dostać się do logiki R. ... jaki jest „najlepszy” sposób na rozpakowanie (na LHS) wyników funkcji zwracającej wiele wartości?
Najwyraźniej nie mogę tego zrobić:
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
czy naprawdę muszę wykonać następujące czynności?
R> r <- functionReturningTwoValues()
R> a <- r[1]; b <- r[2]
lub czy programista R napisałby coś takiego:
R> functionReturningTwoValues <- function() {return(list(first=1, second=2))}
R> r <- functionReturningTwoValues()
R> r$first
[1] 1
R> r$second
[1] 2
--- edytowane, aby odpowiedzieć na pytania Shane'a ---
Naprawdę nie potrzebuję nadawać nazw częściom wartości wynikowej. Stosuję jedną funkcję agregującą do pierwszego komponentu, a drugą do drugiego komponentu ( min
i max
. Jeśli byłaby to ta sama funkcja dla obu komponentów, nie musiałbym ich dzielić).
r
return-value
variable-assignment
assign
multiple-results
mariotomo
źródło
źródło
attr
wartości zwracanej.Odpowiedzi:
(1) lista [...] <- Wysłałem to ponad dekadę temu na r-help . Od tego czasu został dodany do pakietu gsubfn. Nie wymaga specjalnego operatora, ale wymaga napisania lewej strony w następujący sposób
list[...]
:Jeśli potrzebujesz tylko pierwszego lub drugiego komponentu, wszystkie one również działają:
(Oczywiście, jeśli potrzebowałbyś tylko jednej wartości wtedy
functionReturningTwoValues()[[1]]
lubfunctionReturningTwoValues()[[2]]
byłby wystarczający.)Więcej przykładów można znaleźć w cytowanym wątku r-help.
(2) z Jeśli celem jest jedynie połączenie wielu wartości później, a wartości zwracane są nazwane, wówczas można zastosować prostą alternatywę
with
:(3) dołącz Kolejną alternatywą jest załącznik:
DODANE:
with
iattach
źródło
list
i[<-.result
jak tam pokazano?Jakoś natknąłem się na ten sprytny hack w Internecie ... Nie jestem pewien, czy jest to paskudne czy piękne, ale pozwala ci stworzyć „magiczny” operator, który pozwala rozpakować wiele zwracanych wartości do ich własnych zmiennych.
:=
Funkcja zdefiniowana jest tutaj , a zawarte poniżej dla potomnych:Mając to w ręku, możesz robić to, czego szukasz:
Nie wiem jak się z tym czuję. Być może może Ci się to przydać w interaktywnym obszarze roboczym. Wykorzystanie go do budowy (ponownie) użytecznych bibliotek (do masowego użytku) może nie być najlepszym pomysłem, ale myślę, że to zależy od ciebie.
... wiesz, co mówią o odpowiedzialności i władzy ...
źródło
:=
operatora mucho w znacznie bardziejZwykle zawijam dane wyjściowe do listy, która jest bardzo elastyczna (możesz mieć dowolną kombinację liczb, ciągów, wektorów, macierzy, tablic, list, obiektów, w których dane wyjściowe)
tak jak:
źródło
Myślę, że to działa.
źródło
Złożyłem pakiet Zeallot R, aby rozwiązać ten problem. zeallot zawiera wiele zadanie lub rozpakowywanie operatora przypisania
%<-%
. LHS operatora to dowolna liczba zmiennych do przypisania, zbudowana za pomocą wywołań doc()
. RHS operatora to wektor, lista, ramka danych, obiekt daty lub dowolny obiekt niestandardowy z zaimplementowanądestructure
metodą (patrz?zeallot::destructure
).Oto garść przykładów opartych na oryginalnym poście,
Sprawdź winietę opakowania, aby uzyskać więcej informacji i przykładów.
źródło
Nie ma właściwej odpowiedzi na to pytanie. Naprawdę zależy od tego, co robisz z danymi. W prostym powyższym przykładzie zdecydowanie sugerowałbym:
Czy ważne jest, aby powyższe wartości 1 i 2 miały nazwy? Innymi słowy, dlaczego w tym przykładzie ważne jest, aby 1 i 2 były nazywane aib, a nie tylko r [1] ir [2]? Jedną ważną rzeczą, którą należy zrozumieć w tym kontekście, jest to, że aib są jednocześnie wektorami o długości 1. Więc tak naprawdę nic nie zmieniasz w trakcie wykonywania tego przypisania, oprócz posiadania 2 nowych wektorów, które nie wymagają indeksów dolnych, aby odnosić się do:
Możesz także przypisać nazwy oryginalnemu wektorowi, jeśli wolisz odwoływać się do litery niż do indeksu:
[Edytuj] Biorąc pod uwagę, że zastosujesz min i max do każdego wektora osobno, sugerowałbym użycie macierzy (jeśli aib będą tej samej długości i tego samego typu danych) lub ramki danych (jeśli aib będą tej samej długości, ale mogą mieć różne typy danych) lub użyj listy jak w poprzednim przykładzie (jeśli mogą mieć różne długości i typy danych).
źródło
r[1]
może pomóc w wyjaśnieniu (w porządku, nie jeśli imiona takiea
są na swoim miejscu).Listy wydają się idealne do tego celu. Na przykład w ramach funkcji, którą miałbyś
główny program
źródło
Tak, na twoje drugie i trzecie pytanie - właśnie to musisz zrobić, ponieważ nie możesz mieć wielu „wartości” po lewej stronie zadania.
źródło
Co powiesz na użycie przypisania?
Możesz przekazać nazwy zmiennej, którą chcesz przekazać przez referencję.
Jeśli potrzebujesz dostępu do istniejących wartości, odwrotnie
assign
jestget
.źródło
r <- function() { return(list(first=1, second=2)) }
i odwołuje się do wyników za pomocąr$first
ir$second
.Jeśli chcesz zwrócić dane wyjściowe swojej funkcji do środowiska globalnego, możesz użyć
list2env
, podobnie jak w tym przykładzie:Ta funkcja utworzy trzy obiekty w globalnym środowisku:
źródło
[A] Jeśli każdy z foo i taktów jest pojedynczą liczbą, to nie ma nic złego z c (foo, takt); i możesz również nazwać komponenty: c (Foo = foo, Bar = bar). Abyś mógł uzyskać dostęp do składników wyniku „res” jako res [1], res [2]; lub, w podanym przypadku, jako res [„Foo”], res [„BAR”].
[B] Jeśli foo i słupek są wektorami tego samego typu i długości, to znowu nie ma nic złego w zwracaniu cbind (foo, bar) lub rbind (foo, bar); podobnie jak nazwa. W przypadku „cbind” można uzyskać dostęp do foo i bar jako res [, 1], res [, 2] lub jako res [, „Foo”], res [, „Bar”]. Możesz także chcieć zwrócić ramkę danych niż macierz:
i uzyskaj do nich dostęp jako res $ Foo, res $ Bar. Działałoby to również dobrze, gdyby foo i słupek były tej samej długości, ale nie tego samego typu (np. Foo jest wektorem liczb, a wektorem ciąg znaków).
[C] Jeśli foo i bar są wystarczająco różne, aby nie łączyć się wygodnie jak wyżej, to zdecydowanie powinieneś zwrócić listę.
Na przykład twoja funkcja może pasować do modelu liniowego, a także obliczać przewidywane wartości, abyś mógł mieć
a następnie uzyskasz
return list(Foo=foo,Bar=bar)
dostęp do podsumowania jako res $ Foo, przewidywane wartości jako res $ Barźródło: http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html
źródło
Aby uzyskać wiele danych wyjściowych z funkcji i zachować je w żądanym formacie, możesz zapisać dane wyjściowe na dysku twardym (w katalogu roboczym) z poziomu funkcji, a następnie załadować je spoza funkcji:
źródło
Z R 3.6.1 mogę wykonać następujące czynności
źródło