创建一个新的数据框,该数据框的前一个数据框的两列之间的序列中的每个值均带有行

Ama*_*one 1 r dataframe dplyr tidyr tidyverse

我有一个数据框,其中两列代表日期范围的开始和结束。所以:

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
Run Code Online (Sandbox Code Playgroud)

我想创建一个新的数据帧,那里是之间的每个值一列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
Run Code Online (Sandbox Code Playgroud)

理想情况下,这将涉及tidyverse中的某些内容。我一直在尝试使用dplyr::group_by和进行其他操作tidyr::gather,但是我没有任何运气。

akr*_*run 5

我们可以使用map2摆脱“START_YEAR”到“END_YEAR”和序列unnestlist扩展数据为“长”栏格式

library(tidyverse)
df %>%
   transmute(var, year = map2(start_year, end_year, `:`)) %>%
   unnest
#   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
Run Code Online (Sandbox Code Playgroud)

或者另一种选择是 complete

df %>%
     group_by(var) %>% 
     complete(start_year = start_year:end_year) %>% 
     select(var, year = start_year)
Run Code Online (Sandbox Code Playgroud)

base RstackMap

stack(setNames(do.call(Map, c(f = `:`, df[-1])), df$var))
Run Code Online (Sandbox Code Playgroud)

注意:首先使用Map和发布解决方案stack

在其他变化的情况下,

stack(setNames(Map(`:`, df[[2]], df[[3]]), df$var))
stack(setNames(do.call(mapply, c(FUN = `:`, df[-1])), df$var))
Run Code Online (Sandbox Code Playgroud)


Ice*_*can 5

如akrun所示,不使用gatherand 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
Run Code Online (Sandbox Code Playgroud)

这是相同的想法,转换成long并在data.table中扩展(相同的输出)

library(data.table)
setDT(df)

melt(df, 'var')[, .(year = value[1]:value[2]), var]
Run Code Online (Sandbox Code Playgroud)

编辑:正如markus指出的那样,您不需要先使用data.table转换为long,您可以一步完成(不计算上面代码块中的两行library / setDT)。这与akrun的tidyverse答案类似。

df[, .(year = start_year:end_year), by=var]
Run Code Online (Sandbox Code Playgroud)