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

don*_*zao 28 r function dataframe

我使用R遇到了一个小问题......

在以下数据框中

test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) 
Run Code Online (Sandbox Code Playgroud)

我想在v1为1的行中更改v2的值.

test[test$v1==1,"v2"] <- 10
Run Code Online (Sandbox Code Playgroud)

工作得很好.

test
  v1 v2
1  1 10
2  1 10
3  1 10
4  2  0
5  2  0
6  2  0
Run Code Online (Sandbox Code Playgroud)

但是,我需要在函数中执行此操作.

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)
}
Run Code Online (Sandbox Code Playgroud)

调用该函数似乎有效.

test.fun(1)
  v1 v2
1  1 10
2  1 10
3  1 10
4  2  0
5  2  0
6  2  0
Run Code Online (Sandbox Code Playgroud)

但是,当我现在看看测试时:

test
  v1 v2
1  1  0
2  1  0
3  1  0
4  2  0
5  2  0
6  2  0
Run Code Online (Sandbox Code Playgroud)

它不起作用.是否有命令告诉R真正更新函数中的数据框?非常感谢您的帮助!

Jos*_*ich 48

test在你的函数中是来自你的全局环境的对象的副本(我假设它是在它定义的地方).转让发生在当前的环境下,除非另有规定,所以你需要告诉你想要的本地副本分配[R return(test)testtest.

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

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
Run Code Online (Sandbox Code Playgroud)

就个人而言,我会.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
Run Code Online (Sandbox Code Playgroud)


小智 24

在你的函数中改变< - to << -也可以做到这一点,参见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)
Run Code Online (Sandbox Code Playgroud)


Jam*_*mes 9

优良作法是不更改函数中的全局变量,因为这可能会产生不良副作用.为避免在R中出现这种情况,对函数内对象的任何更改实际上只会更改该函数的本地副本environment.

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

 test <- test.fun(1)
Run Code Online (Sandbox Code Playgroud)

或者选择要分配到的全局环境test.fun,

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