【问题标题】:dplyr custom lag function for irregular time seriesdplyr 用于不规则时间序列的自定义滞后函数
【发布时间】:2016-11-09 19:14:40
【问题描述】:

我有一个不规则的时间序列,其中数据集中存在间隙。此外,数据被分组。我已经能够通过观察找到滞后的滞后函数(因此它们在数据集中找到先前的记录),但我想指定一个时间变量并通过匹配滞后时间来计算滞后。这个问题:R lag/lead irregular time series data 正在做类似的事情。但是,我不能使用zoo 解决方案(我有某种包不兼容,根本不能使用zoo)并且未能成功将data.table 解决方案变成足够灵活的东西以用作函数以滞后量作为输入和分组数据的容量。

测试数据:

testdf <- data.frame(group = c(1,1,1,1,1,2,2,2,2,2),
                 counter = c(1,2,3,5,6,7,8,9,11,12),
                 xval = seq(100, 1000, 100))
lagamount <- 1

输出应该是向量:NA 100 200 NA 400 NA 600 700 NA 900

这是我目前正在使用的:

library(dplyr)
testout <- group_by(testdf, group) %>%
  mutate(testout = function(x) which((testdf$counter - x) == lagamount))

这给了我一个数据类型错误,即某些东西(未指定)不是向量。

有没有办法让这个建筑工作?或者,我怎么能滞后于分组变量的不规则时间序列?

【问题讨论】:

  • 或许可以将相关的zoo函数调用为zoo::needed_function(),避免加载包。
  • 你也得到了这个错误,因为你正在向mutate提供一个函数,并且它需要一个向量。
  • 谢谢我应该更清楚 - zoo 不会安装在我的机器上,Rccp 依赖项存在问题。感谢错误信息的解释,我会再试一次

标签: r time-series dplyr


【解决方案1】:

dplyr 中不使用do 的唯一方法是首先明确隐式缺失值,然后将其过滤掉。

提供一个向量进行变异,并使用ifelse(或者可能是新的dplyr::if_else)来检查滞后是否是你想要的。示例:

library(tidyr)
lagamount <- 2

testout <- group_by(testdf, group) %>%
  complete(group, counter = min(counter):max(counter)) %>% 
  mutate(testout = if_else(counter - lag(counter, lagamount) == lagamount, 
                           lag(xval, lagamount), 
                           NA_real_)) %>% 
  filter(!is.na(xval))

生产:

Source: local data frame [10 x 4]
Groups: group [2]

   group counter  xval testout
   <dbl>   <dbl> <dbl>   <dbl>
1      1       1   100      NA
2      1       2   200      NA
3      1       3   300     100
4      1       5   400     300
5      1       6   500      NA
6      2       7   600      NA
7      2       8   700      NA
8      2       9   800     600
9      2      11   900     800
10     2      12  1000      NA

【讨论】:

  • 谢谢。不幸的是,这只适用于单个时间单位滞后。例如,它不能检索之前 2 或 3 个时间单位的值(除非巧合的是之前的观察值)。这就是我尝试与which 合作的原因。
  • 好的,我认为编辑应该可以解决这个问题。否则,您能否给出lagamount = 2 的预期输出?
  • 抱歉,延迟超出了互联网范围。输出肯定看起来像我想要的。是的,将丢失的数据点归档,然后在最后删除它们是一个好方法。将在几分钟内完成并接受。谢谢,我永远无法自己制作这个。
  • 很高兴我能帮上忙。抱歉,我花了几次迭代才明白出了什么问题。
  • 那段代码不是多余的吗?如果您complete() 数据集,您将始终以counter - dplyr::lag(counter, lagamount) == lagamount 结束,不(至少在按计数器排序后)?
【解决方案2】:

当我将上述答案转换为函数时,我最终不得不明确扩展并删除 if_else 中的严格数据类型。这是最终的形式。

getlag <- function(timevar, valuevar, laglength){
  df1 <- data.frame(counter = timevar, value = valuevar, indf = 1)
  alltimes <- data.frame(counter = seq(min(timevar), max(timevar)))
  df2 <- merge(alltimes, df1, all.x = TRUE)
  df2 <- df2 %>%
    mutate(lagvals = ifelse(counter - lag(counter, laglength) == laglength,
                            lag(value, laglength),
                            NA_real_)) %>%
    filter(!is.na(indf))
  return(df2$lagvals)
  }

而测试用例是:

testout <- group_by(testdf, group) %>%
  mutate(testout = getlag(counter, xval, 1))

【讨论】:

    【解决方案3】:

    collapse::flag(以及fdifffgrowth)现在提供了一个有效的解决方案。创建数据时,您需要确保时间变量是整数,否则它将在内部转换为在这种情况下消除不规则性的因子。

    testdf <- data.frame(group = c(1,1,1,1,1,2,2,2,2,2),
                         counter = as.integer(c(1,2,3,5,6,7,8,9,11,12)),
                         xval = seq(100, 1000, 100))
    lagamount <- 1
    

    那么我们可以这样写:

    library(collapse)
    settransform(testdf, L_xval = flag(xval, lagamount, group, counter))
    testdf
    #>    group counter xval L_xval
    #> 1      1       1  100     NA
    #> 2      1       2  200    100
    #> 3      1       3  300    200
    #> 4      1       5  400     NA
    #> 5      1       6  500    400
    #> 6      2       7  600     NA
    #> 7      2       8  700    600
    #> 8      2       9  800    700
    #> 9      2      11  900     NA
    #> 10     2      12 1000    900
    

    reprex package (v0.3.0) 于 2021-07-10 创建

    您还可以选择使用管道生成一系列滞后和领先(或特定滞后/领先顺序):

    testdf |> gby(group) |> flag(-1:3, counter)
    #>    group counter F1.xval xval L1.xval L2.xval L3.xval
    #> 1      1       1     200  100      NA      NA      NA
    #> 2      1       2     300  200     100      NA      NA
    #> 3      1       3      NA  300     200     100      NA
    #> 4      1       5     500  400      NA     300     200
    #> 5      1       6      NA  500     400      NA     300
    #> 6      2       7     700  600      NA      NA      NA
    #> 7      2       8     800  700     600      NA      NA
    #> 8      2       9      NA  800     700     600      NA
    #> 9      2      11    1000  900      NA     800     700
    #> 10     2      12      NA 1000     900      NA     800
    #> 
    #> Grouped by:  group  [2 | 5 (0)]
    

    reprex package (v0.3.0) 于 2021-07-10 创建

    或者使用settransformv进行就地修改:

    settransformv(testdf, "xval", flag, -1:3, group, counter, apply = FALSE)
    testdf
    #>    group counter xval F1.xval L1.xval L2.xval L3.xval
    #> 1      1       1  100     200      NA      NA      NA
    #> 2      1       2  200     300     100      NA      NA
    #> 3      1       3  300      NA     200     100      NA
    #> 4      1       5  400     500      NA     300     200
    #> 5      1       6  500      NA     400      NA     300
    #> 6      2       7  600     700      NA      NA      NA
    #> 7      2       8  700     800     600      NA      NA
    #> 8      2       9  800      NA     700     600      NA
    #> 9      2      11  900    1000      NA     800     700
    #> 10     2      12 1000      NA     900      NA     800
    

    reprex package (v0.3.0) 于 2021-07-10 创建

    fdifffgrowth 的工作方式类似,也支持迭代和复合。您也可以将这些函数应用于不规则的时间序列(没有 panel-id),然后您需要指定t = counter。所有函数都可以应用于向量/时间序列、矩阵/xts、数据帧/数据表/小标题,如果您正在寻找面向对象的方法,还支持plm面板系列和数据帧。

    更多信息请访问:https://sebkrantz.github.io/collapse/reference/time-series-panel-series.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多