web-dev-qa-db-ja.com

関数によるデータフレームの更新が機能しない

Rを使用して少し問題に遭遇しました…

次のデータフレーム

test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) 

V1が1である行のv2の値を変更したい。

test[test$v1==1,"v2"] <- 10

正常に動作します。

test
  v1 v2
1  1 10
2  1 10
3  1 10
4  2  0
5  2  0
6  2  0

ただし、関数でそれを行う必要があります。

test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0)

test.fun <- function (x) {
    test[test$v1==x,"v2"] <- 10
    print(test)
}

関数の呼び出しは機能しているようです。

test.fun(1)
  v1 v2
1  1 10
2  1 10
3  1 10
4  2  0
5  2  0
6  2  0

しかし、今テストを見ると:

test
  v1 v2
1  1  0
2  1  0
3  1  0
4  2  0
5  2  0
6  2  0

うまくいきませんでした。関数のデータフレームを実際に更新するようにRに指示するコマンドはありますか?助けてくれてありがとう!

33
donodarazao

関数内のtestは、グローバル環境からのオブジェクトのcopyです(それが定義されていると想定しています)。特に指定のない限り、割り当ては現在の環境で行われるため、testのローカルコピーを_.GlobalEnv_のtestに割り当てることをRに通知する必要があります。

そして、必要なすべてのオブジェクトを引数として関数に渡すのが適切な形式です。

_test.fun <- function (x, test) {
    test[test$v1==x,"v2"] <- 10
    assign('test',test,envir=.GlobalEnv)
    #test <<- test  # This also works, but the above is more explicit.
}
(test.fun(1, test))
#  v1 v2
#1  1 10
#2  1 10
#3  1 10
#4  2  0
#5  2  0
#6  2  0
_

個人的には、私はreturn(test)で関数の外で割り当てを行いますが、実際の状況でこれを実行できるかどうかはわかりません。

_test.fun <- function (x, test) {
    test[test$v1==x,"v2"] <- 10
    return(test)
}
test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0)
(test <- test.fun(1, test))
#  v1 v2
#1  1 10
#2  1 10
#3  1 10
#4  2  0
#5  2  0
#6  2  0
_
46
Joshua Ulrich

関数で<-<<-に変更すると、トリックも同様に、 R-manual を参照してください。そのページからの引用:

演算子<<-および->>は通常、関数でのみ使用され、割り当てられている変数の既存の定義を親環境で検索します。そのような変数が見つかった場合(およびそのバインディングがロックされていない場合)、その値は再定義されます。それ以外の場合、割り当てはグローバル環境で行われます。

コードは次のようになります。

test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) 

test.fun <- function (x) {
  test[test$v1==x,"v2"] <<- 10
  print(test)
}

test.fun(1)
24
AnitaD

関数のグローバル変数を変更しないことをお勧めします。これは、望ましくない 副作用 が発生する可能性があるためです。 Rでこれを回避するために、関数内のオブジェクトを変更すると、実際にはその関数のenvironmentにローカルなコピーのみが変更されます。

本当にテストを変更したい場合は、テストする関数の戻り値を割り当てる必要があります(より明示的な戻り値で関数を書く方が良いでしょう、

 test <- test.fun(1)

または、test.fun内に割り当てるグローバル環境を選択します。

test.fun <- function (x) {             
    test[test$v1==x,"v2"] <- 10             
    print(test)
    assign("test",test,.GlobalEnv)           
} 
8
James

これは、評価されるenvironmentsが異なるために発生すると思います。関数はtestをグローバル環境から一時的なローカル環境(関数呼び出しで作成される)にコピーし、testはこのローカル環境でのみ評価(つまり変更)されます。

この問題は、スーパー割り当て<<-を使用することで解決できますただし、これは推奨されておらず、恐ろしい予期しない問題が発生します(コンピューターがウイルスに感染し、ガールフレンドがあなたを騙し始めます。 。)。

一般に、ジョシュアウルリッヒによって与えられた解決策は、この種の問題に取り組む方法です。元のオブジェクトを渡して返します。関数呼び出しでは、結果を元のオブジェクトに割り当てます。

2
Henrik

代わりの関数を書くことができます。これは、名前が「<-」で終わり、基本的には次のようにラップされる関数です。

foo = bar(foo)

ラッパー。だからあなたの場合:

> "setV2<-" = function (x,value,m){x[x$v1==m,"v2"]=value;return(x)}
> test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) 
> setV2(test,1)=10
> test
  v1 v2
1  1 10
2  1 10
3  1 10
4  2  0
5  2  0
6  2  0
> setV2(test,2)=99
> test
  v1 v2
1  1 10
2  1 10
3  1 10
4  2 99
5  2 99
6  2 99

作成時に関数名を引用する必要があるか、Rが混乱することに注意してください。

2
Spacedman

* read__csvと呼ばれる関数を作成しました。同じデータに他のr関数にアクセスしたい*

read__csv <- function(files_csv) {
  print(files_csv)
  # set R workign directory as current R file path
  setwd(system("pwd", intern = T) )
  print( getwd() )
  data<-read.csv(files_csv,header = TRUE,na.strings=0)
  print(data)
  assign("data", data, envir = .GlobalEnv)
 #create data varible to r global envrioment 
}

#R Funtion calling
read__csv("csv.csv")

print(data)
0
Mr S Coder