更改data.table r中的多个列

c2e8gylq  于 2023-04-27  发布在  其他
关注(0)|答案(3)|浏览(165)

我正在寻找一种方法来操纵多列的数据。表在R。因为我必须解决列动态以及第二次输入,我无法找到答案。
这个想法是通过将所有值除以日期的值来索引某个日期的两个或多个系列,例如:

set.seed(132)
# simulate some data
dt <- data.table(date = seq(from = as.Date("2000-01-01"), by = "days", length.out = 10),
                 X1 = cumsum(rnorm(10)),
                 X2 = cumsum(rnorm(10)))

# set a date for the index
indexDate <- as.Date("2000-01-05")

# get the column names to be able to select the columns dynamically
cols <- colnames(dt)
cols <- cols[substr(cols, 1, 1) == "X"]

第1部分:简单的数据.框架/应用方法

df <- as.data.frame(dt)
# get the right rownumber for the indexDate
rownum <- max((1:nrow(df))*(df$date==indexDate))

# use apply to iterate over all columns
df[, cols] <- apply(df[, cols], 
                    2, 
                    function(x, i){x / x[i]}, i = rownum)

第2部分:(快速)data.table方法到目前为止,我的data.table方法看起来像这样:

for(nam in cols) {
  div <- as.numeric(dt[rownum, nam, with = FALSE])
  dt[ , 
     nam := dt[,nam, with = FALSE] / div,
     with=FALSE]
}

特别是所有的with = FALSE看起来不太像数据。
你知道有什么更快/更优雅的方法来执行此操作吗?
任何想法都非常赞赏!

xpszyzbs

xpszyzbs1#

一个选择是使用set,因为这涉及多个列。使用set的优点是它将避免[.data.table的开销,并使其更快。

library(data.table)
for(j in cols){
  set(dt, i=NULL, j=j, value= dt[[j]]/dt[[j]][rownum])
}

或者稍微慢一点的选择是

dt[, (cols) :=lapply(.SD, function(x) x/x[rownum]), .SDcols=cols]
kupeojn6

kupeojn62#

根据你的代码和akrun给出的答案,我建议你使用.SDcols来提取数字列,然后使用lapply来循环它们。下面是我的做法:

index <-as.Date("2000-01-05")

rownum<-max((dt$date==index)*(1:nrow(dt)))

dt[, lapply(.SD, function (i) i/i[rownum]), .SDcols = is.numeric]

如果您有大量的数值列,并且希望对所有数值列应用此除法,则使用.SDcols可能特别有用。

4szc88ey

4szc88ey3#

?setdata.table(版本1.14.2)文档中,我发现有一种新的、更简单的方法来实现这一点:
旧的语法曾经是:

DT[i, colvector := val, with = FALSE] # OLD syntax. The contents of "colvector" in calling scope determine the column(s).

新语法为:

DT[i, (colvector) := val] # same (NOW PREFERRED) shorthand syntax. The parens are enough to stop the LHS being a symbol; same as c(colvector).

相关问题