【问题标题】:Creating multiple columns in data table with a for loop使用 for 循环在数据表中创建多列
【发布时间】:2016-09-14 02:03:45
【问题描述】:

我的数据表如下:

head(data)
    Date         AI   AGI      ADI   ASI   ARI   ERI   NVRI  SRI   FRI  IRI
1: 1991-09-06    NA 2094.19    NA    NA    NA    NA    NA    NA    NA    NA
2: 1991-09-13    NA 2204.94    NA    NA    NA    NA    NA    NA    NA    NA
3: 1991-09-20    NA 2339.10    NA    NA    NA    NA    NA    NA    NA    NA
4: 1991-09-27    NA 2387.81    NA    NA    NA    NA    NA    NA    NA    NA
5: 1991-10-04    NA 2459.94    NA    NA    NA    NA    NA    NA    NA    NA
6: 1991-10-11    NA 2571.07    NA    NA    NA    NA    NA    NA    NA    NA

不用担心 NA。我想要做的是为除日期之外的每一列创建一个“百分比变化”列。

到目前为止我所做的是:

names_no_date <- unique(names(data))[!unique(names(data)) %in% "Date"]

for (i in names_no_date){
      data_ch <- data[, paste0(i, "ch") := i/shift(i, n = 1, type = "lag")-1]}

我得到错误:

Error in i/shift(i, n = 1, type = "lag") : 
  non-numeric argument to binary operator

我想知道如何解决这个错误?

【问题讨论】:

  • 请更清楚一点,你所说的“百分比变化”是什么意思——你的意思是增长函数?
  • 您只需将“数字”传递给“二元运算符”即可“绕过它”。您的 i / shift(i, ...) 期望数值作为分子和分母。也许您需要担心NAs?并确保你不是lagging 到一个不存在的行。
  • 如果您使用的是 data.table,请使用 data.table 语法。要创建一个新的 data.table,dt[, lapply(.SD, function(i){i / shift(i)}), .SDcols = -1]。添加到现有的; dt[, paste0(names(dt)[-1], 'ch') := lapply(.SD, function(i){i / shift(i)}), .SDcols = -1]。如果必须使用for 循环,请预先分配适当大小的对象。

标签: r for-loop data.table


【解决方案1】:

i 是一个字符串,所以你试图在i/shift(i, n = 1, type = "lag") 中分割一个字符串:

> "AI"/NA
Error in "AI"/NA : non-numeric argument to binary operator

相反,做

for (i in names_no_date){
      data[, paste0(i, "ch") := get(i)/shift(get(i), n = 1, type = "lag")-1]
}

另见Referring to data.table columns by names saved in variables


编辑:@Frank 在 cmets 中写道,产生 OP 输出的更简洁的方法是

data[, paste0(names_no_date, "_pch") := .SD/shift(.SD) - 1, .SDcols=names_no_date]

【讨论】:

  • 谢谢,太好了!我阅读了 ?get 帮助文件,但我不明白它的作用。你介意解释一下 get() 的作用吗?
  • get("x") 在调用get 的环境中返回名称为“x”的对象。例如,尝试x &lt;- rnorm(5); get("x")
  • ...这就是您 get 解决此错误的方式 *ducks*
  • 你也可以一步完成,我猜:data[, paste0(names_no_date, "_pch") := .SD/shift(.SD) - 1, .SDcols=names_no_date]
  • 嗨@Frank,我很好奇,.SD 是什么意思?
猜你喜欢
  • 1970-01-01
  • 2021-08-15
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-14
相关资源
最近更新 更多