通过功能更新数据帧不起作用

时间:2010-10-19 15:12:23

标签: r function dataframe

我使用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真正更新函数中的数据框? 非常感谢您的帮助!

6 个答案:

答案 0 :(得分:45)

函数中的

test是来自全局环境的对象的副本(我假设它是定义的位置)。除非另有说明,否则在当前环境中进行分配,因此您需要告诉R您要将test的本地副本分配给test中的.GlobalEnv

将所有必要的对象作为参数传递给函数是一种很好的形式。

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

答案 1 :(得分:23)

在您的函数中将&lt; - 更改为&lt;&lt; - ,也可以做到, 见R-manual。从该页面引用:

  

运营商&lt;&lt; - & - &gt;&gt;通常仅在函数中使用,并且通过父环境搜索要分配的变量的现有定义。如果找到这样的变量(并且其绑定未被锁定),则重新定义其值,否则在全局环境中进行赋值。

您的代码应为:

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)

答案 2 :(得分:8)

最好不要在函数中更改全局变量,因为这可能会产生不合需要的side effects。为避免在R中出现这种情况,对函数内对象的任何更改实际上只会更改该函数environment的本地副本。

如果你真的想要改变测试,你必须分配要测试的函数的返回值(用更明确的返回值编写函数会更好,

 test <- test.fun(1)

或者选择要在test.fun内分配的全局环境

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

答案 3 :(得分:2)

我认为这是因为评估的environments不同。您的函数将test从全局环境复制到临时本地环境(在函数调用中创建),然后test仅在此本地环境中进行评估(即更改)。

你可以通过使用超级作业<<-来解决这个问题,但不建议这样做会导致可怕的意外问题(你的计算机发现病毒,你的女朋友开始欺骗你, ...)。

一般来说,Joshua Ulrich给出的解决方案是解决这些问题的方法。您传递原始对象并将其返回。在函数调用上,将结果分配给原始对象。

答案 4 :(得分:2)

你可以写一个替换函数。这是一个名称以'&lt; - '结尾并且基本上将其包装在:

中的函数

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会感到困惑。

答案 5 :(得分:0)

*我创建了一个名为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)