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