将函数应用于多个数据表

raf*_*ira 4 r apply lapply data.table

我有一些具有相同结构的数据表,我想对它们进行一些数据转换(创建新变量,分配缺失值等)

这是我尝试过的,没有成功.此代码运行正常,但不会更改数据表.有任何想法吗?

有关可重现的示例,请先运行此代码段

data("mtcars")              # load data
setDT(mtcars)               # convert to data table
mtcars[gear==5, gear :=NA]  # create NA values for the purpose of my application
mtcars2 <- mtcars           # create second DT
Run Code Online (Sandbox Code Playgroud)

我的代码

# Create function
  computeWidth <- function(dataset){
                                    dataset$gear[is.na(dataset$gear)] <- 0 # Convert NA to 0
                                    dataset[ ,width := hp + gear]          # create new variable
                                    }

# Apply function
  lapply(list(mtcars, mtcars2), computeWidth)
Run Code Online (Sandbox Code Playgroud)

如您所见,该函数有效,但它没有修改数据表.你对此有何看法?

Dav*_*urg 6

您的主要问题是您使用的语法不正确.而不是dataset$gear[is.na(dataset$gear)] <- 0你应该使用dataset[is.na(gear), gear := 0],这种方式:=将修改你的原始数据集在词法范围之外lapply(<-某个函数的词法范围内运行).从而修改你的功能

computeWidth <- function(dataset){
  dataset[is.na(gear), gear := 0] # Convert NA to 0
  dataset[ ,width := hp + gear]   # create new variable
}
Run Code Online (Sandbox Code Playgroud)

然后跑

lapply(list(mtcars, mtcars2), computeWidth) 
Run Code Online (Sandbox Code Playgroud)

将修改原始数据集.

作为旁注,如果您想将此概括为多个data.table对象,您可以查看该tables函数并尝试以下内容

lapply(mget(tables(silent = TRUE)$NAME), computeWidth)
Run Code Online (Sandbox Code Playgroud)

虽然最好先将多个对象放在一个列表中,而不是用许多对象填充全局环境.


一个非常重要的注释(由@Frank建议),您应该知道<-在未修改时使用时data.table实际上并不是在创建新对象

mtcars2 <- mtcars
tracemem(mtcars)
## [1] "<00000000129264F8>"
tracemem(mtcars2)
## [1] "<00000000129264F8>"
Run Code Online (Sandbox Code Playgroud)

因此,通过只修改mtcars你也将修改mtcars2.相反,正确的做法是使用,copy

mtcars2 <- copy(mtcars)
tracemem(mtcars)
## [1] "<00000000129264F8>"
tracemem(mtcars2)
## [1] "<000000001315F6B8>"
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参见此处