首页 > 解决方案 > 如何根据预定义的序列识别滞后变量

问题描述

我有一个时间序列,我想生成一个新变量,该变量等于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

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

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

标签: rtime-seriestidyverse

解决方案


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

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)))



推荐阅读