【问题标题】:Why is rbind not working inside a user defined function?为什么 rbind 在用户定义的函数中不起作用?
【发布时间】:2020-12-01 00:27:21
【问题描述】:

我正在尝试将行附加到用户定义函数内的数据框。我之前在 for 循环中没有困难地做到过,如下:

t1 <- data.frame(a=character(),
                 b=numeric())
for(i in 1:2){
    tmp.df <- data.frame(a="apple", b=i)
    t1 <- rbind(t1,tmp.df)
}

我得到一个包含两个观察结果的数据框。

但是当我尝试在函数中做类似的事情时,它不起作用。我已经尝试调试该函数,并且在 rbind 步骤它似乎只是退出该函数而不执行该步骤。所以下面的代码以原始的空数据框结束。

t1 <- data.frame(a=character(),
                 b=numeric())

create.rows <- function(id, it){
  if(it==1){
    
    tmp.df <- data.frame(a=id, b=it)
    t1 <- rbind(t1,tmp.df)
  }else{
    tmp.df <- data.frame(a=id, b=99)
    t1 <- rbind(t1,tmp.df)
  }
}

为什么会发生这种情况,我可以做些什么来解决它?

请注意,我事先不知道数据框中会有多少行,因此我无法直接写入特定行。

【问题讨论】:

  • “它不起作用”。它是什么”。仅仅创建一个函数没有任何作用。

标签: r function rbind


【解决方案1】:

在函数中,需要指定赋值运算符的&lt;&lt;- 形式,以使 R 搜索父环境以找到赋值运算符左侧的对象并为其分配新值。

t1 <- data.frame(a=character(),
                 b=numeric())

create.rows <- function(id, it){
     if(it==1){
          
          tmp.df <- data.frame(a=id, b=it)
          t1 <<- rbind(t1,tmp.df)
     }else{
          tmp.df <- data.frame(a=id, b=99)
          t1 <<- rbind(t1,tmp.df)
     }
}

create.rows(1,1)
create.rows(1,2)
t1

...和输出:

> t1
  a  b
1 1  1
2 1 99

有关三种形式的赋值运算符(=&lt;-&lt;&lt;-)行为的更多详细信息,请查看assignment operator 的帮助页面,其中相关部​​分显示:

> 运算符通常只用在函数中,并导致通过父环境搜索被分配变量的现有定义。如果找到这样的变量(并且其绑定未锁定),则重新定义其值,否则在全局环境中进行赋值。

【讨论】:

  • 声明:需要指定赋值运算符的&lt;&lt;-形式,才能让R在父环境中搜索,找到赋值运算符左侧的对象。 i> 非常具有误导性。这是否意味着&lt;-=-&gt; 不搜索父环境?我相信他们会。区别在于&lt;&lt;-重新定义环境中的对象(显然是在对象的绑定解锁时)而&lt;-没有
  • 你好@Onyambu。我不同意你对我回答的描述。我阅读 Software for Data Analysis 第 5.4 节的方式,&lt;&lt;- 运算符的要点是从函数内部执行非本地分配,根据定义,它重新定义了对象的值父环境。
  • 非常感谢 - 我以前从未遇到过这个赋值运算符。
  • @Susan - 不客气。如果您发现答案有帮助,请接受和/或投票。顺便说一句,Ronak Shah 的回答也有效。
  • &lt;- 也完全符合您的上述要求。就是这样,我说该声明具有误导性。 &lt;&lt;-&lt;- 的主要区别在于后者不能用于REDEFINE 变量。可能您的提示应该是需要指定赋值运算符的&lt;&lt;- 形式以让R 搜索父环境以找到赋值运算符左侧的对象并重新定义它跨度>
【解决方案2】:

return函数末尾的更改数据框。

t1 <- data.frame(a=character(),
                 b=numeric())

create.rows <- function(id, it){

  if(it==1){
    tmp.df <- data.frame(a=id, b=it)
    t1 <- rbind(t1,tmp.df)
  }else{
    tmp.df <- data.frame(a=id, b=99)
    t1 <- rbind(t1,tmp.df)
  }
  return(t1)
}

t1 <- create.rows(1,1)
t1
#  a b
#1 1 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-12
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    相关资源
    最近更新 更多