Frage

Immer noch versuchen, in die R-Logik zu bekommen ... was ist der „beste“ Weg (auf LHS) die Ergebnisse aus einer Funktion zurückkehr mehrere Werte zu entpacken?

Ich kann das nicht tun offenbar:

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

muss ich wirklich tun die folgende?

R> r <- functionReturningTwoValues()
R> a <- r[1]; b <- r[2]

oder würde das R-Programmierer schreiben etwas mehr wie folgt aus:

R> functionReturningTwoValues <- function() {return(list(first=1, second=2))}
R> r <- functionReturningTwoValues()
R> r$first
[1] 1
R> r$second
[1] 2

--- bearbeitet Shane Fragen zu beantworten ---

Ich brauche nicht wirklich Namen den Ergebniswert Teile geben. Ich beantrage eine Aggregatfunktion auf die erste Komponente und eine andere mit dem zweiten Bauteil (min und max., Wenn sie die gleiche Funktion für beide Komponenten war, würde ich sie nicht brauchen Splitting).

War es hilfreich?

Lösung

(1) Liste [...] <- ich das mehr als ein Jahrzehnt geschrieben hatte vor auf r Hilfe . Seitdem hat es sich zum gsubfn Paket hinzugefügt. Sie stellen keine besonderen Betreiber verlangen, aber nicht erforderlich, dass die linke Seite list[...] wie folgt aus geschrieben werden:

library(gsubfn)  # need 0.7-0 or later
list[a, b] <- functionReturningTwoValues()

Wenn Sie nur die erste oder zweite Komponente diese alle zu arbeiten:

list[a] <- functionReturningTwoValues()
list[a, ] <- functionReturningTwoValues()
list[, b] <- functionReturningTwoValues()

(Natürlich, wenn Sie nur einen Wert benötigen dann functionReturningTwoValues()[[1]] oder functionReturningTwoValues()[[2]] wäre ausreichend.)

Sehen Sie die zitierte r-Hilfe-Thread für weitere Beispiele.

(2) mit Wenn es die Absicht, nur ist es, die mehrere Werte anschließend und die Rückgabewerte genannt werden kombinieren dann eine einfache Alternative ist with zu verwenden:

myfun <- function() list(a = 1, b = 2)

list[a, b] <- myfun()
a + b

# same
with(myfun(), a + b)

(3) befestigen Eine weitere Alternative ist anbringt:

attach(myfun())
a + b

ADDED: with und attach

Andere Tipps

Ich stolperte irgendwie auf dieser cleveren Hack im Internet ... Ich bin nicht sicher, ob es böse oder schön, aber es kann Sie einen „magischen“ Operator erstellen, die Sie mehrere Rückgabewerte in die eigene Variable entpacken kann. Die := Funktion ist hier definiert, und auch weiter unten für Nachwelt:

':=' <- function(lhs, rhs) {
  frame <- parent.frame()
  lhs <- as.list(substitute(lhs))
  if (length(lhs) > 1)
    lhs <- lhs[-1]
  if (length(lhs) == 1) {
    do.call(`=`, list(lhs[[1]], rhs), envir=frame)
    return(invisible(NULL)) 
  }
  if (is.function(rhs) || is(rhs, 'formula'))
    rhs <- list(rhs)
  if (length(lhs) > length(rhs))
    rhs <- c(rhs, rep(list(NULL), length(lhs) - length(rhs)))
  for (i in 1:length(lhs))
    do.call(`=`, list(lhs[[i]], rhs[[i]]), envir=frame)
  return(invisible(NULL)) 
}

Damit in der Hand, können Sie tun, was Sie nach:

functionReturningTwoValues <- function() {
  return(list(1, matrix(0, 2, 2)))
}
c(a, b) := functionReturningTwoValues()
a
#[1] 1
b
#     [,1] [,2]
# [1,]    0    0
# [2,]    0    0

Ich weiß nicht, was ich davon fühlen. Vielleicht finden Sie es in Ihrem interaktiven Arbeitsplatz hilfreich. Mit ihm (Wieder-) verwendbaren Bibliotheken zu bauen (für den Massenkonsum) ist vielleicht nicht die beste Idee, aber ich denke, das ist bis zu Ihnen.

... Sie wissen, was sie sagen, über Verantwortung und Macht ...

In der Regel wickeln ich die Ausgabe in eine Liste, die sehr flexibel ist (Sie eine beliebige Kombination von Zahlen haben, Strings, Vektoren, Matrizen, Arrays, Listen, Objekte int er Ausgabe)

so wie:

func2<-function(input) {
   a<-input+1
   b<-input+2
   output<-list(a,b)
   return(output)
}

output<-func2(5)

for (i in output) {
   print(i)
}

[1] 6
[1] 7
functionReturningTwoValues <- function() { 
  results <- list()
  results$first <- 1
  results$second <-2
  return(results) 
}
a <- functionReturningTwoValues()

Ich denke, das funktioniert.

ich zusammen ein R-Paket zeallot dieses Problem in Angriff zu nehmen. zeallot umfasst eine Mehrfachzuordnung oder Auspacken Zuweisungsoperator, %<-%. Die LHS der Bedienungsperson eine beliebige Anzahl von Variablen ist, zuzuweisen gebaut Anrufe mit bis c(). Der RHS des Betreibers ist ein Vektor, Liste, Datenrahmen, Datum Objekt oder über individuelle Objekt mit einer implementierten destructure Methode (siehe ?zeallot::destructure).

Hier sind ein paar Beispiele auf der Grundlage der ursprünglichen Nachricht,

library(zeallot)

functionReturningTwoValues <- function() { 
  return(c(1, 2)) 
}

c(a, b) %<-% functionReturningTwoValues()
a  # 1
b  # 2

functionReturningListOfValues <- function() {
  return(list(1, 2, 3))
}

c(d, e, f) %<-% functionReturningListOfValues()
d  # 1
e  # 2
f  # 3

functionReturningNestedList <- function() {
  return(list(1, list(2, 3)))
}

c(f, c(g, h)) %<-% functionReturningNestedList()
f  # 1
g  # 2
h  # 3

functionReturningTooManyValues <- function() {
  return(as.list(1:20))
}

c(i, j, ...rest) %<-% functionReturningTooManyValues()
i     # 1
j     # 2
rest  # list(3, 4, 5, ..)

Überprüfen Sie das Paket Vignette out für weitere Informationen und Beispiele.

Es gibt keine richtige Antwort auf diese Frage. Ich hängt wirklich davon ab, was Sie mit den Daten tun. In dem einfachen Beispiel oben würde ich dringend empfehlen:

  1. Halten Sie die Dinge so einfach wie möglich.
  2. Wo immer möglich, es ist eine bewährte Methode, Ihre Funktionen vektorisiert zu halten. Das bietet die größte Menge an Flexibilität und Geschwindigkeit auf lange Sicht.

Ist es wichtig, dass die Werte 1 und 2 Namen haben? Mit anderen Worten, warum ist es wichtig, dass in diesem Beispiel 1 und 2 a und b genannt werden, und nicht nur r [1] und r [2]? Eine wichtige Sache in diesem Zusammenhang zu verstehen ist, dass a und b auch beide Vektoren der Länge 1. Sie sind also nicht wirklich etwas zu ändern in dem Prozess der, dass die Zuordnung zu machen, anders als mit 2 neuen Vektoren dass nicht Indizes müssen referenziert werden:

> r <- c(1,2)
> a <- r[1]
> b <- r[2]
> class(r)
[1] "numeric"
> class(a)
[1] "numeric"
> a
[1] 1
> a[1]
[1] 1

Sie können auch die Namen auf den ursprünglichen Vektor zuweisen, wenn Sie lieber den Brief als der Index verweisen würden:

> names(r) <- c("a","b")
> names(r)
[1] "a" "b"
> r["a"]
a 
1 

[Bearbeiten] Da Sie min und max auf jeden Vektor separat anwenden wird, würde ich vorschlagen, entweder unter Verwendung einer Matrix (wenn a und b die gleiche Länge und den gleichen Datentyp sein) oder Datenrahmen (wenn a und b gleich lang sein, sondern kann verschiedene Datentypen sein) oder auch eine Liste wie im letzten Beispiel verwenden (wenn sie mit unterschiedlichen Längen und Datentypen sein können).

> r <- data.frame(a=1:4, b=5:8)
> r
  a b
1 1 5
2 2 6
3 3 7
4 4 8
> min(r$a)
[1] 1
> max(r$b)
[1] 8

Listen scheinen perfekt für diesen Zweck. Zum Beispiel in der Funktion würden Sie haben

x = desired_return_value_1 # (vector, matrix, etc)

y = desired_return_value_2 # (vector, matrix, etc)

returnlist = list(x,y...)

}  # end of function

Hauptprogramm

x = returnlist[[1]]

y = returnlist[[2]]

Ja, um Ihre zweite und die dritte Frage -. Das ist, was Sie tun müssen, da Sie nicht mehrere ‚lvalues‘ auf der linken Seite einer Zuweisung haben

Wie wäre es mit zuweisen?

functionReturningTwoValues <- function(a, b) {
  assign(a, 1, pos=1)
  assign(b, 2, pos=1)
}

Sie können die Namen der Variablen übergeben Sie als Referenz übergeben werden soll.

> functionReturningTwoValues('a', 'b')
> a
[1] 1
> b
[1] 2

Wenn Sie die vorhandenen Werte zugreifen müssen, das Gegenteil von assign ist get.

[A] Wenn jeder von foo und bar eine einzelne Zahl ist, dann gibt es nichts falsch mit c (foo, bar); und Sie können auch die Komponenten nennen: c (Foo = foo, Bar = bar). So könnte man die Komponenten des Ergebnis 'res' zugreifen, als res [1], res [2]; oder in dem genannten Fall, wie res [ "Foo"], res [ "BAR"].

[B] Wenn foo und bar sind Vektoren der gleichen Art und Länge, dann wieder gibt es nichts falsch mit der Rückkehr cbind (foo, bar) oder rbind (foo, bar); ebenfalls benennbar. Im 'cbind' Fall würden Sie foo Zugang und eine Bar als res [1], res [2] oder als res [ "Foo"], res [ "Bar"]. Vielleicht haben Sie auch lieber einen Datenrahmen zurückzukehren lieber als eine Matrix:

data.frame(Foo=foo,Bar=bar)

und auf sie zugreifen, wie res $ Foo, res $ Bar. Dies würde auch gut, wenn foo und bar von gleicher Länge waren aber nicht vom gleichen Typ (zum Beispiel foo ein Vektor von Zahlen, Bar einen Vektor von Zeichenkette).

[C] Wenn foo und bar ausreichend verschieden sind nicht bequem, wie oben zu kombinieren, dann shuld Sie auf jeden Fall eine Liste zurück.

Zum Beispiel Ihre Funktion könnte ein lineares Modell passen und auch berechnen Werte vorhergesagt, so könnten Sie haben

LM<-lm(....) ; foo<-summary(LM); bar<-LM$fit

und dann würden Sie return list(Foo=foo,Bar=bar) und dann die Zusammenfassung zugreifen wie $ Foo res, die vorhergesagten Werte wie $ Bar res

Quelle: http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html

Wenn Sie die Ausgabe Ihrer Funktion zur Globalen Umwelt zurückkehren möchten, können Sie list2env, wie in diesem Beispiel verwenden:

myfun <- function(x) { a <- 1:x
                       b <- 5:x
                       df <- data.frame(a=a, b=b)

                       newList <- list("my_obj1" = a, "my_obj2" = b, "myDF"=df)
                       list2env(newList ,.GlobalEnv)
                       }
    myfun(3)

Mit dieser Funktion werden drei Objekte in der Global Environment erstellen:

> my_obj1
  [1] 1 2 3

> my_obj2
  [1] 5 4 3

> myDF
    a b
  1 1 5
  2 2 4
  3 3 3

Um mehrere Ausgänge aus einer Funktion zu erhalten und bewahren Sie sie im gewünschten Format können Sie die Ausgänge auf der Festplatte speichern (im Arbeitsverzeichnis) innerhalb der Funktion und laden sie dann von außerhalb der Funktion:

myfun <- function(x) {
                      df1 <- ...
                      df2 <- ...
                      save(df1, file = "myfile1")
                      save(df2, file = "myfile2")
}
load("myfile1")
load("myfile2")
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top