data.table 在函数中使用时的奇怪行为
data.table weird behaviour when used in a function
我有一个data.frame
如下。
data <- structure(list(V1 = structure(1:3, .Label = c("S01", "S02", "S03"), class = "factor"), V2 = structure(c(1L, 3L, 2L), .Label = c("Alan", "Bruce", "Jay"), class = "factor"), V3 = structure(c(3L, 1L, 2L), .Label = c("Barry", "Dick", "Hal"), class = "factor"), V4 = structure(c(1L, 3L, 2L), .Label = c("Guy", "Jean-Paul", "Wally"), class = "factor"), V5 = structure(c(3L, 1L, 2L), .Label = c("Bart", "Damien", "John"), class = "factor")), .Names = c("V1", "V2", "V3", "V4", "V5"), class = "data.frame", row.names = c(NA, -3L))
这不是 data.table
is.data.table(data)
[1] FALSE
例如,我有一个函数 foo
,它利用 data.table
在 data.frame
中进行如下操作。
foo <- function(df) {
if(!is.data.frame(df)) stop('"df" is not a data.frame')
setDT(df)
setkey(df, V1)
df[, "NEW" := paste0(V3, V4), with = FALSE]
setDF(df)
return(df)
}
然而,当我 运行 带有 data.frame
data
的函数(不是 data.table
)时,输出 out
是 data.frame
(因为 setDF(df)
)。
out <- foo(data)
is.data.table(out)
[1] FALSE
但是现在原来的data.frame
data
变成了data.table
.
is.data.table(data)
[1] TRUE
我理解这是因为 data.table
是通过引用工作的。但是在函数中使用时如何处理这个问题。我不想无意中更改环境中的任何 data.frame。每当在函数中使用 data.table
时,我是否应该始终使用 copy
或 <-
而不是 setDT
强制复制,还是有其他方法?
关于
is there another way?
而不是函数内部的 setDT()
,您可以使用 as.data.table()
foo <- function(df) {
if(!is.data.frame(df)) stop('"df" is not a data.frame')
df <- as.data.table(df)
setkey(df, V1)
df[, NEW := paste0(V3, V4)]
setDF(df)
return(df)
}
foo(data)
# V1 V2 V3 V4 V5 NEW
# 1 S01 Alan Hal Guy John HalGuy
# 2 S02 Jay Barry Wally Bart BarryWally
# 3 S03 Bruce Dick Jean-Paul Damien DickJean-Paul
is.data.table(data)
# [1] FALSE
有关将输入数据 frame 转换为数据 table 但不更改原始数据的一些函数示例数据框,我绝对建议查看包 splitstackshape
.
中函数的源代码
我有一个data.frame
如下。
data <- structure(list(V1 = structure(1:3, .Label = c("S01", "S02", "S03"), class = "factor"), V2 = structure(c(1L, 3L, 2L), .Label = c("Alan", "Bruce", "Jay"), class = "factor"), V3 = structure(c(3L, 1L, 2L), .Label = c("Barry", "Dick", "Hal"), class = "factor"), V4 = structure(c(1L, 3L, 2L), .Label = c("Guy", "Jean-Paul", "Wally"), class = "factor"), V5 = structure(c(3L, 1L, 2L), .Label = c("Bart", "Damien", "John"), class = "factor")), .Names = c("V1", "V2", "V3", "V4", "V5"), class = "data.frame", row.names = c(NA, -3L))
这不是 data.table
is.data.table(data)
[1] FALSE
例如,我有一个函数 foo
,它利用 data.table
在 data.frame
中进行如下操作。
foo <- function(df) {
if(!is.data.frame(df)) stop('"df" is not a data.frame')
setDT(df)
setkey(df, V1)
df[, "NEW" := paste0(V3, V4), with = FALSE]
setDF(df)
return(df)
}
然而,当我 运行 带有 data.frame
data
的函数(不是 data.table
)时,输出 out
是 data.frame
(因为 setDF(df)
)。
out <- foo(data)
is.data.table(out)
[1] FALSE
但是现在原来的data.frame
data
变成了data.table
.
is.data.table(data)
[1] TRUE
我理解这是因为 data.table
是通过引用工作的。但是在函数中使用时如何处理这个问题。我不想无意中更改环境中的任何 data.frame。每当在函数中使用 data.table
时,我是否应该始终使用 copy
或 <-
而不是 setDT
强制复制,还是有其他方法?
关于
is there another way?
而不是函数内部的 setDT()
,您可以使用 as.data.table()
foo <- function(df) {
if(!is.data.frame(df)) stop('"df" is not a data.frame')
df <- as.data.table(df)
setkey(df, V1)
df[, NEW := paste0(V3, V4)]
setDF(df)
return(df)
}
foo(data)
# V1 V2 V3 V4 V5 NEW
# 1 S01 Alan Hal Guy John HalGuy
# 2 S02 Jay Barry Wally Bart BarryWally
# 3 S03 Bruce Dick Jean-Paul Damien DickJean-Paul
is.data.table(data)
# [1] FALSE
有关将输入数据 frame 转换为数据 table 但不更改原始数据的一些函数示例数据框,我绝对建议查看包 splitstackshape
.