如何向 data.table 添加一列并返回多列而不修改基础数据?

jon*_*nsh 3 r dataframe data.table

我有以下data.table内容R

dt <- data.table(gender = c("Male", "Female"), Prop = c(0.49, 0.51))
#   gender Prop
# 1:   Male  0.49
# 2: Female  0.51
Run Code Online (Sandbox Code Playgroud)

我想计算一Freq = Prop * 1000列,然后仅返回gender和Freq列。如何在一行代码中完成此操作,而无需显式引用该gender列且无需修改dt?

我能做到的最好的办法是:

onsdist$gender[, c(.SD, Freq = Prop * 1000)][, .SD, .SDcols = - "Prop"]
#    gender Freq1 Freq2
# 1:   Male   490   490
# 2: Female   510   510
Run Code Online (Sandbox Code Playgroud)

但我最终得到了重复的Freq列。

(我不想引用的原因gender是因为它跨data.tables改变了。我不想修改的原因dt是因为以后需要重新使用原始版本)。

G. *_*eck 5

1)使用 Prop = NULL 的变换

dt[, transform(.SD, Freq = Prop * 1000, Prop = NULL)]
##    gender Freq
## 1:   Male  490
## 2: Female  510
Run Code Online (Sandbox Code Playgroud)

2)或这种变体

transform(dt, Freq = Prop * 1000, Prop = NULL)
##    gender Freq
## 1:   Male  490
## 2: Female  510
Run Code Online (Sandbox Code Playgroud)

3)我们可以通过用折叠包中的ftransform替换transform来大大加快速度。

library(collapse)
dt[, ftransform(.SD, Freq = Prop * 1000, Prop = NULL)]
Run Code Online (Sandbox Code Playgroud)

4)同样

library(collapse)
ftransform(dt, Freq = Prop * 1000, Prop = NULL)
Run Code Online (Sandbox Code Playgroud)

基准

使用问题中的数据,我们可以看到上面的 (4)(下面标记为 ex4),它使用来自塌陷的 ftransform 而不使用 [.data.table ,比上面的其他方法快得多。

library(collapse)
library(data.table)
library(microbenchmark)

microbenchmark(
    ex1 = dt[, transform(.SD, Freq = Prop * 1000, Prop = NULL)],
    ex2 = transform(dt, Freq = Prop * 1000, Prop = NULL),
    ex3 = dt[, ftransform(.SD, Freq = Prop * 1000, Prop = NULL)],
    ex4 = ftransform(dt, Freq = Prop * 1000, Prop = NULL)
)

Unit: microseconds
 expr      min       lq       mean    median       uq      max neval  cld
  ex1 1847.601 1927.402 2046.04098 2015.4015 2093.251 2706.200   100    d
  ex2  959.700 1000.701 1074.93098 1046.1510 1122.601 1606.201   100  b  
  ex3 1048.201 1090.351 1139.57598 1121.6005 1174.201 1381.602   100   c 
  ex4   68.401   85.551   93.08802   89.2515  100.551  168.400   100 a   
Run Code Online (Sandbox Code Playgroud)