setDT()不添加其他列

时间:2016-06-06 22:40:54

标签: r data.table

我正在使用setDT()将其他列添加到data.table但

setDT(mydata)[, paste0('F2_E',2:30) := lapply(.SD, function(x) log(value/x)), .SDcols = 32:60][]
运行此脚本时未添加

library(data.table)
library(zoo)
date = seq(as.Date("2016-01-01"),as.Date("2016-05-10"),"day")
value =seq(1,131,1)
mydata = data.frame (date, value)
mydata
setDT(mydata)[, paste0('F1',2:30) := lapply(2:30, function(x) rollmeanr(value, x, fill = rep(NA,x-1)) ),][]
setDT(mydata)[, paste0('F2',2:30) := lapply(2:30, function(x) rollapply(value,x,FUN="median",align="right",fill=NA))][]
setDT(mydata)[, paste0('F1_E',2:30) := lapply(.SD, function(x) log(value/x)     ), .SDcols = 3:31][]
setDT(mydata)[, paste0('F2_E',2:30) := lapply(.SD, function(x) log(value/x)), .SDcols = 32:60][]
rbind(colnames(mydata))


rbind(colnames(mydata))
     [,1]   [,2]    [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]  [,10] [,11]  [,12]  [,13]  [,14]  [,15]  [,16]  [,17]  [,18]  [,19]  [,20]  [,21]  [,22]  [,23]  [,24]  [,25]  [,26]  [,27] 
[1,] "date" "value" "F12" "F13" "F14" "F15" "F16" "F17" "F18" "F19" "F110" "F111" "F112" "F113" "F114" "F115" "F116" "F117" "F118" "F119" "F120" "F121" "F122" "F123" "F124" "F125" "F126"
     [,28]  [,29]  [,30]  [,31]  [,32] [,33] [,34] [,35] [,36] [,37] [,38] [,39] [,40]  [,41]  [,42]  [,43]  [,44]  [,45]  [,46]  [,47]  [,48]  [,49]  [,50]  [,51]  [,52]  [,53]  [,54] 
[1,] "F127" "F128" "F129" "F130" "F22" "F23" "F24" "F25" "F26" "F27" "F28" "F29" "F210" "F211" "F212" "F213" "F214" "F215" "F216" "F217" "F218" "F219" "F220" "F221" "F222" "F223" "F224"
     [,55]  [,56]  [,57]  [,58]  [,59]  [,60]  [,61]   [,62]   [,63]   [,64]   [,65]   [,66]   [,67]   [,68]   [,69]    [,70]    [,71]    [,72]    [,73]    [,74]    [,75]    [,76]    [,77]   
[1,] "F225" "F226" "F227" "F228" "F229" "F230" "F1_E2" "F1_E3" "F1_E4" "F1_E5" "F1_E6" "F1_E7" "F1_E8" "F1_E9" "F1_E10" "F1_E11" "F1_E12" "F1_E13" "F1_E14" "F1_E15" "F1_E16" "F1_E17" "F1_E18"
     [,78]    [,79]    [,80]    [,81]    [,82]    [,83]    [,84]    [,85]    [,86]    [,87]    [,88]    [,89]   
[1,] "F1_E19" "F1_E20" "F1_E21" "F1_E22" "F1_E23" "F1_E24" "F1_E25" "F1_E26" "F1_E27" "F1_E28" "F1_E29" "F1_E30"

你可以看到没有F2_E2,F2_E3等......列。

为什么不添加这些列?

2 个答案:

答案 0 :(得分:2)

简短回答:

使用setDT(mydata)一次,然后单独使用。然后完成所有作业陈述。

此外,如果您要添加大量列,请使用函数alloc.col()预先分配更多插槽,直到下一个版本(v1.9.8)。即,

setDT(mydata)
truelength(mydata) # [1] 100
alloc.col(mydata, 1000L)
truelength(mydata) # [1] 1000

current development version, v1.9.7中,默认情况下我们将过度分配增加到了1024。所以这应该很少发生。

快速而细致的解释:

这是因为data.table 在创建过程中过度分配列指针,而默认的 over-allocation 长度为100列。您可以使用truelength()进行检查。请参阅?truelength

require(data.table)
mydata = data.frame (x=1, y=2)
setDT(mydata)      ## convert to data.table by reference
length(mydata)     ## equals the columns assigned
# [1] 2
truelength(mydata) ## total number of column slots allocated
# [1] 100

让我们按照您的方式添加30多列。

setDT(mydata)[, paste0("z", 1:30) := 1L]
length(mydata)     ## [1] 32
truelength(mydata) ## [1] 100

另外30岁。

setDT(mydata)[, paste0("z", 31:60) := 1L]
length(mydata)     ## [1] 62
truelength(mydata) ## [1] 100

另外30岁。

setDT(mydata)[, paste0("z", 61:90) := 1L]
length(mydata)     ## [1] 92
truelength(mydata) ## [1] 100

现在,下次我们执行此操作时,我们还要添加30个列,但我们只有 8 更多的广告位。因此,我们需要创建具有更多过度分配的插槽的另一个对象,将当前位于mydata的所有列分配给新对象,最后将其分配回mydata。这是内部和自动处理的,因此用户不必跟踪。所以下次我们这样做:

setDT(mydata)[, paste0("z", 91:120) := 1L]

函数[.data.table意识到它需要再次过度分配,并且这样做,并且新列被添加到新对象中。问题是将此新对象的结果分配回mydata的父框架中的[.data.table。这是通过assign()语句完成的,该语句只接受变量名作为字符输入,setDT(mydata)不是。{1}}。因此重新分配步骤失败,因此过度分配不能反映回原始对象。如果您已完成mydata[, paste0(..) := ...],则输入对象mydata名称,可用于将过度分配的结果分配回原始对象,并且这就是@thelatemail的建议可行的原因。

如果这太高级,只需升级到devel版本,这一切都会消失,并且不太可能发生(除非你想要在数据中包含超过1024列) 。表)。

我已提交#1731提醒我们回过头来看看是否还有其他方法可以解决此问题。

答案 1 :(得分:0)

我遇到了与你相同的问题。我们可以尝试ping data.table专家来理解这个问题。 @latemail获取所需的输出,因此它适用于某人。

与此同时,由于您在第三次和第四次调用上运行相同的操作,我们可以将它们合并为一个以获得所需的输出:

mydata[, paste0(rep(c('F1_E', 'F2_E'),each=29), rep(2:30, 2)) := lapply(.SD, function(x) log(value/x)), .SDcols = 3:60][]

 dim(mydata)
[1] 131 118

修改

删除方括号,它将起作用。我会抓住我的头一段时间,直到找出原因。