在data.table中转换*some*列类

arv*_*000 22 r data.table

我想将data.table cols的子集转换为新类.这里有一个流行的问题(在data.table中转换列类)但是答案创建了一个新对象,而不是在starter对象上运行.

举个例子:

dat <- data.frame(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
cols <- c('ID', 'Quarter')
Run Code Online (Sandbox Code Playgroud)

如何最好地将cols列转换为(例如)一个因子?在普通的data.frame中,你可以这样做:

dat[, cols] <- lapply(dat[, cols], factor)
Run Code Online (Sandbox Code Playgroud)

但这对data.table不起作用,也不适用

dat[, .SD := lapply(.SD, factor), .SDcols = cols]
Run Code Online (Sandbox Code Playgroud)

来自Matt Dowle(2013年12月)的链接问题中的评论表明以下情况很好,但看起来不那么优雅.

for (j in cols) set(dat, j = j, value = factor(dat[[j]]))
Run Code Online (Sandbox Code Playgroud)

目前是否有更好的data.table答案(即更短+不生成计数器变量),或者我应该只使用上面的+ rm(j)

Jaa*_*aap 44

除了使用Matt Dowle建议的选项外,另一种更改列类的方法如下:

dat[, (cols) := lapply(.SD, factor), .SDcols = cols]
Run Code Online (Sandbox Code Playgroud)

通过使用:=运算符,您可以通过引用更新数据表.检查一下是否有效:

> sapply(dat,class)
       ID   Quarter     value 
 "factor"  "factor" "numeric" 
Run Code Online (Sandbox Code Playgroud)

正如@MattDowle在评论中所建议的那样,您还可以使用for(...) set(...)如下组合:

for (col in cols) set(dat, j = col, value = factor(dat[[col]]))
Run Code Online (Sandbox Code Playgroud)

这将得到相同的结果.第三种选择是:

for (col in cols) dat[, (col) := factor(dat[[col]])]
Run Code Online (Sandbox Code Playgroud)

在较小的数据集上,该for(...) set(...)选项比lapply选项快三倍(但这并不重要,因为它是一个小数据集).在较大的数据集(例如,200万行)上,这些方法中的每一种花费大约相同的时间量.为了测试更大的数据集,我使用了:

dat <- data.table(ID=c(rep("A", 1e6), rep("B",1e6)),
                  Quarter=c(1:1e6, 1:1e6),
                  value=rnorm(10))
Run Code Online (Sandbox Code Playgroud)

有时,您必须以不同的方式执行此操作(例如,将数值存储为因子时).然后你必须使用这样的东西:

dat[, (cols) := lapply(.SD, function(x) as.integer(as.character(x))), .SDcols = cols]
Run Code Online (Sandbox Code Playgroud)

警告: 下面的解释是不是data.table做的事情的三通.数据表不是通过引用更新的,因为副本被创建并存储在内存中(如@Frank所指出的),这会增加内存使用量.它更多是为了解释工作的补充with = FALSE.

如果要以与使用数据帧相同的方式更改列类,则必须with = FALSE按如下方式添加:

dat[, cols] <- lapply(dat[, cols, with = FALSE], factor)
Run Code Online (Sandbox Code Playgroud)

检查一下是否有效:

> sapply(dat,class)
       ID   Quarter     value 
 "factor"  "factor" "numeric" 
Run Code Online (Sandbox Code Playgroud)

如果不添加with = FALSE,datatable将评估dat[, cols]为向量.检查dat[, cols]和之间的输出差异dat[, cols, with = FALSE]:

> dat[, cols]
[1] "ID"      "Quarter"

> dat[, cols, with = FALSE]
    ID Quarter
 1:  A       1
 2:  A       2
 3:  A       3
 4:  A       4
 5:  A       5
 6:  B       1
 7:  B       2
 8:  B       3
 9:  B       4
10:  B       5
Run Code Online (Sandbox Code Playgroud)

  • 在`:=`的RHS上使用`lapply`可能是内存效率低下,而不是``=`本身.更多细节[这里](http://stackoverflow.com/a/33000778/403310)关于为什么`for(...)set(...)`使用最少的内存.但在这种情况下,每列上对`factor()`的调用可能占主导地位. (3认同)
  • @Jaap新编辑不仅仅是速度,还有峰值内存使用.对于较大的数据集,它可以在工作或不工作之间产生差异(带有`:= lapply`方式的内存不足错误).感谢这些问题和评论,我提出了一个问题来优化这一点,因此用户不需要知道这些差异,[#1441](https://github.com/Rdatatable/data.table/issues/1441). (3认同)