gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 14:10:57 25 4
gpt4 key购买 nike

我将 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 中(几乎)每个修改都是在先前数据的副本上执行的(copy-on-writing 行为)。
因此,例如在您的函数内部,当您执行 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

N.B.

在这种特定情况下,循环可以替换为“矢量化”和更有效的版本,例如:
d[d$value %% 2 == 0,'value'] <- 0

但也许您真正的循环代码更加复杂,无法轻松矢量化。

关于R:通过引用函数传递 data.frame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33186633/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com