繁体   English   中英

R:通过引用函数传递data.frame

[英]R: Pass data.frame by reference to a function

我将data.frame作为参数传递给想要更改内部数据的函数:

x <- data.frame(value=c(1,2,3,4))
f <- function(d){
  for(i in 1:nrow(d)) {
    if(d$value[i] %% 2 == 0){
      d$value[i] <-0
    }
  }
  print(d)
}

当我执行f(x)我可以看到data.frame内部是如何被修改的:

> f(x)
  value
1     1
2     0
3     3
4     0

但是,我传递的原始data.frame是未修改的:

> x
  value
1     1
2     2
3     3
4     4

通常我通过返回修改后的一个克服了这个:

f <- function(d){
  for(i in 1:nrow(d)) {
    if(d$value[i] %% 2 == 0){
      d$value[i] <-0
    }
  }
  d
}

然后调用重新分配内容的方法:

> x <- f(x)
> x
  value
1     1
2     0
3     3
4     0

但是,我想知道这个行为在一个非常大的data.frame中是什么影响,是一个为方法执行而增长的新东西? R-ish这样做的方法是什么?

有没有办法修改原始的,而不在内存中创建另一个?

实际上在R(几乎)中,每个修改都在先前数据的副本上执行(写时复制行为)。
因此,例如在您的函数内部,当您执行d$value[i] <-0实际创建了一些副本。 您通常不会注意到,因为它已经过优化,但您可以使用tracemem函数进行跟踪。

话虽这么说,如果你的data.frame不是很大,你可以坚持使用你的函数返回修改过的对象,因为它只是一个副本。

但是,如果您的数据集非常大并且每次都进行复制可能非常昂贵,那么您可以使用data.table,它允许就地修改,例如:

library(data.table)
d <- data.table(value=c(1,2,3,4))
f <- function(d){
  for(i in 1:nrow(d)) {
    if(d$value[i] %% 2 == 0){
      set(d,i,1L,0) # special function of data.table (see also ?`:=` )
    }
  }
  print(d)
}

f(d)
print(d)

# results :
> f(d)
   value
1:     1
2:     0
3:     3
4:     0
> 
> print(d)
   value
1:     1
2:     0
3:     3
4:     0

NB

在这种特定情况下,循环可以用“矢量化”和更有效的版本替换,例如:

d[d$value %% 2 == 0,'value'] <- 0

但也许你真正的循环代码更复杂,不能轻易地进行矢量化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM