2016-08-08 11 views
0

私は次の問題で頭を悩ましています:リスト付きforループの関数を作成する

いくつかのデータフレームに依存するパラメータを持つforループ内に2つの関数を作成しています。各機能はリストの中に入れられます。

forループ内のパラメータを表示すると、eachh関数が適切に定義されていることがわかります。しかし、ループの外側にあるものを使用すると、最後のパラメータだけが両方の関数に使用されます。次の例では、それを明確にする必要があります。

dt <- data.frame(color = c("red", "blue"), 
       a = c(3,9), 
       b = c(1.3, 1.8)) 
function_list <- list() 
for (col in dt$color) { 
    a <- dt$a[dt$color == col] 
    b <- dt$b[dt$color == col] 

    foo <- function(x) { 
     a*x^b 
    } 
    print(paste(col, foo(1))) 
    function_list[[col]] <- foo 
} 

[1] "3赤" [1] "ブルー9"

function_list[["red"]](1) 

[1] 9

function_list[["blue"]](1) 
get作品(前回の質問に対する私の答え)と R nested for loop to write multiple functions and plot them

同等のソリューション:0

は、[1] 9

に注意することは、これは、次の質問からインスピレーションを得ています。

+1

私はなぜあなたが驚いているのか分かりません。関連する 'a'と' b'の値は、関数を呼び出すときの値であり、関数の定義時ではありません。 – Roland

+0

@Roland関数内で定数値を動的に割り当てる正しい方法は何ですか? – thepule

+0

私は、一見、同等の解決策が割り当てられ、うまくいくという事実にほとんど驚いていました。私は今、割り当てを使用してソリューションを以前に与えられた唯一のプロットが新しいループ内で行われた偶然から働いたことを実現...ありがとう。 – Choubi

答えて

0

関連する値abは、関数を呼び出すときの値であり、定義したときの値ではありません。あなたがリストを作成する方法は、それらは地球環境から取られます。解決策は、closuresを作成することです。私はこのためMapを使用すると思いますが、あなたはforループと同じ操作を行うことができます。

funs <- Map(function(a, b) function(x) a*x^b, a = dt$a, b = dt$b) 

print(funs) 
#[[1]] 
#function (x) 
#a * x^b 
#<environment: 0x000000000a9a4298> 
# 
#[[2]] 
#function (x) 
#a * x^b 
#<environment: 0x000000000a9a3728> 

は異なる環境に注意してください。

environment(funs[[1]])$a 
#[1] 3 
environment(funs[[2]])$a 
#[1] 9 

funs[[1]](1) 
#[1] 3 
funs[[2]](1) 
#[1] 9 
0

あなたの混乱は、あなたのコードが動作しない理由のは、確認してみましょうEnvironments

とビット深く行くことによって解決されます。 print(function_list)を試すと、格納されている関数の両方がa*x^bを返すことがわかります。

# Part 1 : Why it doesn't work 
# -------------------------- 

print(function_list) 
# $red 
# function (x) 
# { 
# a * x^b 
# } 
# 
# $blue 
# function (x) 
# { 
# a * x^b 
# } 

あなたがaを削除し、機能を再実行しようとすると、エラーが返されます。

rm(a) 
function_list[['red']](1) 
# Error in function_list[["red"]](1) : object 'a' not found 

そのほとんどがどちらかあなたの環境で遊んやデータ構造を変更する必要があります、それを動作させるために複数の方法があります:

そして今、あなたのコードを機能させるためにどのように

環境を管理する方法の1つは、値を保持し、グローバル環境で変数を検索しないように、関数から関数を返すことです。私たちはfunction_listに何があるかチェックしている場合

# Part 2 : How to make it work 
# ---------------------------- 

function_list <- list() 
for (col in dt$color) { 

    a <- dt$a[dt$color == col] 
    b <- dt$b[dt$color == col] 

    foo1 <- function(inner.a, inner.b) { 
    return(function(x) {inner.a*x^inner.b}) 
    } 

    foo2 <- foo1(a,b) 
    print(paste(col, foo2(1))) 

    function_list[[col]] <- foo2 
} 

さて、あなたは関数が2つの環境

print(function_list) 

# $red 
# function (x) 
# { 
# inner.a * x^inner.b 
# } 
# <environment: 0x186fb40> 
# 
# $blue 
# function (x) 
# { 
# inner.a * x^inner.b 
# } 
# <environment: 0x2536438> 

期待通りの出力でもあるであることがわかります。 aを削除しても、期待どおりに動作します。

function_list[['red']](1) # 3 
function_list[['blue']](1) # 9 

rm(a) 
function_list[['red']](1) #[1] 3 
0

は、私がabの値は、地球環境にfooで撮影しているので、ループのため、彼らがどこにあるか、(あなたがループ内print(environment)ことで、これを確認することができます)新しい環境を作成していないと思う9と1.8、すなわちそれらの最後に割り当てられた値。

関連する問題