【问题标题】:fill datatable column iteratively迭代地填充数据表列
【发布时间】:2018-08-24 10:30:38
【问题描述】:

使用初始值,我想根据 id 存储在单独列中的增长率迭代地填充 data.table 列中的 NA。

以如下data.table为例:

library(data.table)
DT <- data.table(id = c("A","A","A","A","B","B","B","B"),  date=1:4,
 growth=1L+runif(8), index= c(NA,250,NA,NA,NA,300,NA,NA))

> DT
   id date   growth index
1:  A    1 1.654628    NA
2:  A    2 1.770219   250
3:  A    3 1.255893    NA
4:  A    4 1.185985    NA
5:  B    1 1.826187    NA
6:  B    2 1.055251   300
7:  B    3 1.180389    NA
8:  B    4 1.204108    NA

基本上,日期 2 之后的索引值需要 id:

index_{i,t} = 增长_{i,t}*index_{i,t-1}

并且,对于日期 2 之前的值:

index_{i,t} = index_{i,t-1}/growth_{i,t-1}

我曾尝试使用 shift,但这只是替换 t+1 处的索引:

DT[, index := growth * shift(index,1L, type="lag")]  

更新 想要的结果是这样的

> DT
   id date   growth    index
1:  A    1 1.440548 141.2255
2:  A    2 1.395092 250.0000
3:  A    3 1.793094 313.9733
4:  A    4 1.784224 372.3676
5:  B    1 1.129264 284.2926
6:  B    2 1.978359 300.0000
7:  B    3 1.228979 354.1167
8:  B    4 1.453433 426.3948

【问题讨论】:

  • 听起来您想按日期进行子集化,并按 id 分组;例如,像 DT[date &gt; 2, index2 := growth * shift(index,1L, type="lag"), by = id]DT[date &lt; 2, index2 := shift(index,1L) / shift(growth, 1L), by = id] 。这使得您的示例数据的所有 NA 。你的目标是填满所有的 NA 吗?
  • @ChrisHolbrook:确实,我们的目标是填补所有的 NA。问题在于,使用 shift 命令我们可以填充一个观察值。但是由于下一次填充需要这个新填充的观察,所以命令不符合目标,对吧?

标签: r data.table panel-data data-management


【解决方案1】:

首先,我们将定义一个函数,它采用两个向量,valuesgrowths,即

  1. values 中查找第一个非NA
  2. 通过将growths 与非NA 之间的所有growths 相乘,确定values 中每个元素与非NA 的比率。
  3. 是乘法吗

请注意,这不会捕获有多个非NA 值的情况,如果values 仅具有NAs 则会出错。但是我把异常处理留给你,因为你最清楚该怎么做。

apply_growth <- function(values, growths) {
  given <- which(!is.na(values))[1]

  cumulative_growth <- vapply(
    X = seq_along(growths),
    FUN.VALUE = numeric(1),
    FUN = function(x) {
      if (x < given) {
        1 / prod(growths[seq(x + 1, given)])
      } else if (x > given) {
        prod(growths[seq(given + 1, x)])
      } else if (x == given) {
        1
      }
    }
  )

  values[given] * cumulative_growth
}

现在我们将其应用于DT 的每个子组。为确定起见,我们将指定行必须按date 排序。

DT[
  order(date),
  index := apply_growth(index, growth),
  by = id
]

DT
#    id date   growth    index
# 1:  A    1 1.993863 180.7514
# 2:  A    2 1.383115 250.0000
# 3:  A    3 1.350102 337.5256
# 4:  A    4 1.863802 629.0809
# 5:  B    1 1.664999 249.2398
# 6:  B    2 1.203660 300.0000
# 7:  B    3 1.595310 478.5931
# 8:  B    4 1.002311 479.6989

【讨论】:

  • 这看起来很棒!非常感谢在此停留了一段时间
  • 一个更矢量化的累积增长公式:cumprod(c(1/growths[2:given], growths[given:length(growths)])) ... 如果给定 == 1,则需要进行一些编辑。
猜你喜欢
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多