5

exp1exp2およびの 3 つのリストに保存する 3 つの実験を使用していますexp3。各リストにはいくつかの項目 ( nameconditionsdataset_adataset_bなど) があります。すべての実験に対して操作を実行したい場合があります。名前を変数に保存して動的に呼び出す方法はありますか? これは機能しません:

all_exp <- list(exp1=exp1,exp2=exp2,exp3=exp3)

後で実験に何かを追加した場合all_exp、参照ではなく、以前の状態での実験のハード コピーがあるためです。

この種の作品:

all_exp_names <- c("exp1","exp2","exp3")
all_exp <- lapply(all_exp_names, function(exp_name) (eval(parse(text=exp_name))))

しかし、もっと簡単な方法が必要です。さらに、返されたリストから実験名が失われます。

4

2 に答える 2

7

私はあなたが欲しいと思います

lapply(all_exp_names,get)

しかし、それは実際には名前付きリストを返しません。できるよ

setNames(lapply(all_exp_names,get),all_exp_names)

確かに少し不格好ですが、頻繁に使用する場合は関数にパッケージ化できます(これに対するわずかに優れた解決策については、@ JoshOBrienの回答を参照してください)。

もっと慣用的なことは、最初にデータの参照コピーを名前付きリストに保持することだと思います。

編集: 以下の私の元の遅延代入/評価コードは巧妙でしたが、R に組み込みdelayedAssign関数があるという点を完全に見逃していましたmakeDelayVar

delayedAssign("exp_all",list(exp1=exp1,exp2=exp2))

(do.call のおかげで、curve は、これを指摘するために別の関数環境内に関数をプロットすることはできません%<%。)ただし、以下に示すように中置演算子を定義するトリックは、依然として便利な場合があります。


遅延割り当てが本当に必要 な場合は、これが機能します(ただし、単純ではありません):

makeActiveBinding("all_exp",function() list(exp1=exp1,exp2=exp2), .GlobalEnv)
exp1 <- 2
exp2 <- 3
all_exp
## $exp1
## [1] 2
##  
## $exp2
## [1] 3

makeDelayVar評価環境に注意する必要があるかもしれませんが、これを関数でラップすることもできます。

makeDelayVar <- function(var,val) {
   makeActiveBinding(deparse(substitute(var)), function() val, parent.frame())
}
makeDelayVar(all_exp, list(exp1=exp1,exp2=exp2))
all_exp

これは上記と同じように機能します (この手順が実際に遅延評価を行っていることを確認したい場合は、 and を削除exp1exp2、 を定義all_expしてから再定義できます)。exp[12]

さらに愚かなことをするため%<%に、遅延代入を行うように定義できます (R では、中置演算子を として定義できます%[character]%)。

`%<%` <- makeDelayVar
all_exp %<% list(exp1,exp2)

ただし、これは注意して使用します。状況によっては壊れやすい可能性があります。たとえば、それが壊れたり何かおかしいことをした場合にすぐにわかるインタラクティブなコンテキストに制限し、遅延評価の結果を引数として関数などに渡そうとしないでください。

于 2013-01-05T18:04:52.277 に答える
7

名前を保持したい場合は、次を使用できますsapply(..., simplify=FALSE, USE.NAMES=TRUE)

A <- B <- C <- 1:4
nms <- c("A", "B", "C")

sapply(nms, get, simplify=FALSE, USE.NAMES=TRUE)
## $A
## [1] 1 2 3 4
## 
## $B
## [1] 1 2 3 4
## 
## $C
## [1] 1 2 3 4
于 2013-01-05T19:10:19.480 に答える