data.table在函数中使用时的奇怪行为

时间:2015-01-22 19:47:51

标签: r dataframe data.table

我有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.tabledata.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)运行该函数时,输出outdata.frame(因为{{ 1}})。

setDF(df)

但现在原来的out <- foo(data) is.data.table(out) [1] FALSE data.framedata

data.table

我理解这是因为is.data.table(data) [1] TRUE 通过引用工作。但是在函数中使用时如何处理这个问题。我不想“无意中改变环境中的任何data.frame”。我是否应该在函数中使用data.table时强制使用copy<-而不是setDT进行复制,还是有其他方式?

1 个答案:

答案 0 :(得分:2)

关于

  

还有另一种方法吗?

您可以使用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), with = FALSE]
    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 转换为数据的函数的一些示例,但根本不更改原始数据框,我绝对建议您查看包splitstackshape中函数的源代码。