有没有办法为介于两个时间点之间的年份创建虚拟变量?

Is there a way to create dummy variables for years that fall between two time points?

我正在处理一些时间序列数据,其中每一行都是对一个人的观察,我有两个时间段,开始日期和结束日期。我正在尝试为每一年创建虚拟变量,这样如果年份介于开始日期和结束日期之间,则虚拟变量编码为 1。

最终结果是将其用于按年统计的人口统计数据可视化目的。

我查看了一些包,但它似乎从已经提供的变量中创建了虚拟对象。由于其中一列可能缺少某些年份,因此我正在尝试寻找替代选项。

id <- c(1:3)
start.date <- c(1990, 1850, 1910)
end.date <- c(2014, 1920, 1980)

df <- data.frame(id, start.date, end.date)

df

正如您从数据结构中看到的那样,例如,我希望个人 1 将 1990 年至 2014 年间的假人编码为 1,否则为 0。

如果我没理解错的话,你想要一个包含所有年份的数据框 -

library(dplyr)
library(tidyr)

df %>% 
  group_by(id) %>% 
  transmute(years = list(paste0("Y", start.date:end.date)), value = 1) %>% 
  unnest() %>% 
  ungroup() %>% 
  spread(years, value, fill = 0)

# showing first 10 of total 157 columns
# A tibble: 3 x 10
     id Y1850 Y1851 Y1852 Y1853 Y1854 Y1855 Y1856 Y1857 Y1858
  <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     0     0     0     0     0     0     0     0     0
2     2     1     1     1     1     1     1     1     1     1
3     3     0     0     0     0     0     0     0     0     0

另一种使用 tidyr::expand 而不是 dplyr::transmute 的方法。

df1 <- data.frame(id = c(1:3),
                  start.date = c(1990, 1850, 1910),
                  end.date = c(2014, 1920, 1980))
library(dplyr)
library(tidyr)
df1 %>%
  group_by(id) %>% 
  expand(year = start.date:end.date) %>% 
  mutate(value = 1, year = paste0("Y",year)) %>% 
  ungroup %>% 
  spread(year, value, fill = 0)

#> # A tibble: 3 x 157
#>      id Y1850 Y1851 Y1852 Y1853 Y1854 Y1855 Y1856 Y1857 Y1858 Y1859 Y1860
#>   <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     0     0     0     0     0     0     0     0     0     0     0
#> 2     2     1     1     1     1     1     1     1     1     1     1     1
#> 3     3     0     0     0     0     0     0     0     0     0     0     0
#> # ... with 145 more variables: Y1861 <dbl>, Y1862 <dbl>, Y1863 <dbl>,...

这是一个基本的方法:

seqs <- df$end.date - df$start.date+1

table(data.frame(id = rep(df[['id']], seqs)
           , Y = paste0('Y', rep(df[['start.date']], seqs) + sequence(seqs) - 1)))

   Y
id  Y1850 Y1851 Y1852 Y1853 Y1854 Y1855 Y1856 Y1857 Y1858 Y1859 ... lots of columns
  1     0     0     0     0     0     0     0     0     0     0
  2     1     1     1     1     1     1     1     1     1     1
  3     0     0     0     0     0     0     0     0     0     0