258

まだ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

--- シェーンの質問に答えるために編集 ---

結果の値の部分に名前を付ける必要はありません。1 つの集計関数を最初のコンポーネントに適用し、別の集計関数を 2 番目のコンポーネントに適用しています (両方のコンポーネントで同じ関数minmaxある場合は、それらを分割する必要はありません)。

4

15 に答える 15

211

(1) list[...]<-これは 10 年以上前にr-helpに投稿しました。それ以来、gsubfn パッケージに追加されています。特別な演算子は必要ありませんが、左辺を次のlist[...]ように記述する必要があります。

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

最初または 2 番目のコンポーネントのみが必要な場合は、これらもすべて機能します。

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

(もちろん、必要な値が 1 つだけの場合は、functionReturningTwoValues()[[1]]またはfunctionReturningTwoValues()[[2]]で十分です。)

他の例については、引用された r-help スレッドを参照してください。

(2) with 後で複数の値を単に組み合わせることが目的であり、戻り値に名前が付けられている場合、単純な代替手段は次を使用することwithです。

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

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

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

(3) attachもう 1 つの方法は attach です。

attach(myfun())
a + b

追加:withおよびattach

于 2013-02-28T16:23:36.630 に答える
71

私はどういうわけかインターネットでこの巧妙なハックに出くわしました...それが厄介なのか美しいのかはわかりませんが、複数の戻り値を独自の変数に解凍できる「魔法の」演算子を作成できます。:=関数はここで定義され、後世のために以下に含まれています。

':=' <- 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)) 
}

それを手にすると、あなたはあなたが求めていることをすることができます:

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

それについてどう思うかわかりません。おそらく、インタラクティブなワークスペースで役立つかもしれません。(大量消費のために)(再)使用可能なライブラリを構築するためにそれを使用することは最善の考えではないかもしれませんが、それはあなた次第だと思います。

...あなたは彼らが責任と権力について何を言っているか知っています...

于 2009-12-01T23:21:19.600 に答える
59

通常、出力を非常に柔軟なリストにラップします (数値、文字列、ベクトル、行列、配列、リスト、オブジェクトを任意に組み合わせて出力できます)。

以下のようなので:

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
于 2009-12-01T15:01:58.310 に答える
16
functionReturningTwoValues <- function() { 
  results <- list()
  results$first <- 1
  results$second <-2
  return(results) 
}
a <- functionReturningTwoValues()

これはうまくいくと思います。

于 2016-03-23T14:46:36.623 に答える
10

この質問に対する正しい答えはありません。私はあなたがデータで何をしているかに本当に依存しています。上記の単純な例では、次のことを強くお勧めします。

  1. 物事をできるだけシンプルに保ちます。
  2. 可能な限り、関数をベクトル化しておくことをお勧めします。これにより、長期的には最大の柔軟性と速度が得られます。

上記の値 1 と 2 に名前があることは重要ですか? 言い換えれば、この例で 1 と 2 を単に r[1] と r[2] ではなく、a と b という名前にすることが重要なのはなぜでしょうか? このコンテキストで理解しておくべき重要なことの 1 つは、a と b両方とも長さ 1 のベクトルであるということです。したがって、添字を必要としない 2 つの新しいベクトルを持つこと以外は、その割り当てを行う過程で実際には何も変更していません。参照する:

> 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

インデックスではなく文字を参照する場合は、元のベクトルに名前を割り当てることもできます。

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

[編集]各ベクトルに最小値と最大値を個別に適用することを考えると、マトリックス (a と b が同じ長さと同じデータ型の場合) またはデータ フレーム (a と b が同じ場合) を使用することをお勧めします。同じ長さですが、データ型が異なる場合があります)、または最後の例のようにリストを使用します (長さとデータ型が異なる場合)。

> 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
于 2009-12-01T14:42:15.830 に答える
6

リストは、この目的に最適のようです。たとえば、関数内で

x = desired_return_value_1 # (vector, matrix, etc)

y = desired_return_value_2 # (vector, matrix, etc)

returnlist = list(x,y...)

}  # end of function

メインプログラム

x = returnlist[[1]]

y = returnlist[[2]]
于 2013-02-28T15:41:58.237 に答える
4

2 番目と 3 番目の質問に「はい」 - 割り当ての左側に複数の「左辺値」を指定できないため、これが必要です。

于 2009-12-01T14:41:39.567 に答える