【问题标题】:How to identify lag variable based on a pre-defined sequence如何根据预定义的序列识别滞后变量
【发布时间】:2019-10-23 11:28:08
【问题描述】:

我有一个时间序列,我想生成一个新变量,该变量等于上一年变量value 的值。

我的问题是,在时间序列的第一年,当我生成滞后变量时,我得到了 NA。 value 的内容遵循重复模式,但 id 的模式不同。

理论上,应该能够对观察到的value序列进行模式匹配,并使用已知模式填充滞后变量中的NA,但我不知道如何解决这个问题。

我尝试将模式序列连接到数据,并将其转换为宽,因此我为序列的每个元素添加了三个新列。我在想我可能能够以某种方式根据去年的数据值循环遍历列。但由于序列的性质,我意识到我需要对整个序列进行模式匹配,而不是一次只匹配一个值。

data <- tibble(
  year=rep(2015:2018,3),
  id=c(rep('A',4),rep('B',4),rep('C',4)),
  value=c('CG','SB','CG','CG',
          'CG','CG','CG','CG',
          'CG','SB','CG','SB')
)

data.seq <- tibble(
  seq1=c('CG','CG','SB'),
  seq2=c('CG','CG',NA),
  seq3=c('CG','SB',NA)
)

# Generate new variable that has 'value' of previous year
data <- data %>% 
  group_by(id) %>%
  mutate(
    lagValue = lag(value)
  )

# Need to fill in the NA's based on the sequences in data.seq

为了帮助回答这个问题,我手动输入了给定data.seq 中序列的 ​​NA 的输出:

expected.data <- data
expected.data[c(1,5,9),'lagValue'] <- c('CG','CG','SB')

【问题讨论】:

  • 你能发布预期的输出吗?

标签: r time-series tidyverse


【解决方案1】:

我创建了一种排序功能供您使用。

library(tidyverse)

data <- tibble(
  year = rep(2015:2018, 3),
  id = c(rep('A', 4), rep('B', 4), rep('C', 4)),
  value = c(
    'CG',
    'SB',
    'CG',
    'CG',
    'CG',
    'CG',
    'CG',
    'CG',
    'CG',
    'SB',
    'CG',
    'SB'
  )
)

# lookup list for ids and sequence
data.seq <- list()
data.seq$A <- c('CG', 'CG', 'SB')
data.seq$B <- c('CG', 'CG')
data.seq$C <- c('CG', 'SB')


findPos <- function(value, group) {

  # select sequence according to group
  currentSeq <- data.seq[[unique(group)]]

  # get rid of NAs
  seqMatch <- currentSeq[!is.na(currentSeq)]

  # multiplier for sequence
  compareLength <- length(value) + length(seqMatch) - 1

  multi <- compareLength / length(seqMatch)
  mod <- compareLength %% length(seqMatch)

  if (mod > 0) {
    multi <- as.integer(multi) + 1

  }

  # multiple sequence
  seqMatch <- rep(seqMatch, multi)

  i <- 1
  # search und rotate position until match is found
  repeat {
    if (identical(lag(value)[!is.na(lag(value))], 
                  seqMatch[i:(length(value) - 2 + i)])) {

      # if found on first position, add another sequence at the beginning
      if (length(seqMatch[i - 1]) == 0) {
        return(c(currentSeq, seqMatch)[length(currentSeq)+i-1])

      } else {
        return(seqMatch[i - 1])
      }

    }

    i <- i + 1

  }

}

data <- data %>%
  group_by(id) %>%
  mutate(lagValue = ifelse(is.na(lag(value)), 
                           findPos(value, id), 
                           lag(value)))


【讨论】:

  • 谢谢@Patrick。我认为这是一个有趣的方法。唯一可能不起作用的是,在我的真实数据中,唯一 ID 值的数量是数百个。因此,根据组手动选择序列的seqMatch 变量很难对整个数据实现。您对如何将其转换为自动选择有任何想法吗?
  • 这取决于您如何提供 ID 和相应的序列。我用查找列表和更稳定的序列匹配版本更新了我的示例。您还可以继续为 ID 和序列使用嵌套的 tibble。
猜你喜欢
  • 1970-01-01
  • 2019-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多