我有一个数据框,其中两列代表日期范围的开始和结束。所以:
df <- data.frame(var=c("A", "B"), start_year=c(2000, 2002), end_year=c(2005, 2004))
> df
var start_year end_year
1 A 2000 2005
2 B 2002 2004
我想创建一个新的数据框,其中 start_year
和 end_year
之间的每个值都有一行,对于每个 var
.
所以结果应该是这样的:
> newdf
var year
1 A 2000
2 A 2001
3 A 2002
4 A 2003
5 A 2004
6 A 2005
7 B 2002
8 B 2003
9 B 2004
理想情况下,这会涉及 tidyverse 中的内容。我一直在用 dplyr::group_by
和 tidyr::gather
尝试不同的东西,但我没有任何运气。
正如 akrun 所展示的,如果没有 gather
和 group_by
(如问题中所述),这样做可能更容易。但是如果你好奇如何那样做,就在这里
df %>%
gather(key, value, -var) %>%
group_by(var) %>%
expand(year = value[1]:value[2])
# # A tibble: 9 x 2
# # Groups: var [2]
# var year
# <fct> <int>
# 1 A 2000
# 2 A 2001
# 3 A 2002
# 4 A 2003
# 5 A 2004
# 6 A 2005
# 7 B 2002
# 8 B 2003
# 9 B 2004
这里是同样的想法,转换为 long 并展开,在 data.table 中(相同的输出)
library(data.table)
setDT(df)
melt(df, 'var')[, .(year = value[1]:value[2]), var]
编辑:正如 markus 指出的那样,您不需要先使用 data.table 转换为 long,您可以一步完成(不包括上面代码块中的两行 library/setDT)。这是与 akrun 的 tidyverse 答案类似的方法。
df[, .(year = start_year:end_year), by=var]