dplyr自定义滞后函数用于不规则时间序列

时间:2016-07-07 12:50:55

标签: r time-series dplyr

我有一个不规则的时间序列,数据集中存在空白。此外,数据被分组。滞后函数我已经能够通过观察找到滞后(因此他们找到数据集中的先前记录),但我想指定一个时间变量并通过匹配滞后时间计算滞后。这个问题: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))

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

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

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:0)

当我将上述答案转换为函数时,我最终必须明确地展开扩展并删除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))

答案 2 :(得分:0)

现在在 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 年 7 月 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 年 7 月 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 年 7 月 10 日创建

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

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