R - 基于列减法为记录的每一年创建行

R - Create Row for Each Year of a Record based on column subtraction

我在 R 中有一个关于志愿服务的数据框。我想为志愿服务的每个财政年度排成一行。所以我的数据是这样的:

ID  Volunteership   FYStart FYEnd
1   Fabulousness    2019    2021
2   Graciousness    2021    2021
3   Loveliness  1995    1999

我需要为涉及的每个财政年度创建一个新行,并且需要一个“VolFY”列来标记每个。我需要结束:

ID  Volunteership   FYStart FYEnd   VolFY
1   Fabulousness    2019    2021    2019
1   Fabulousness    2019    2021    2020
1   Fabulousness    2019    2021    2021
2   Graciousness    2021    2021    2021
3   Loveliness  1995    1999    1995
3   Loveliness  1995    1999    1996
3   Loveliness  1995    1999    1997
3   Loveliness  1995    1999    1998
3   Loveliness  1995    1999    1999

到目前为止,我玩过 seq()rep()。我也玩过 for 循环和 while 循环,但还没有完全掌握正确的技巧。

如果你做过这种事,请分享你是怎么做到的。这是一个难题。

--玛丽安

tidyverse-

中有一种方法
library(tidyverse)

df %>%
  mutate(VolFY = map2(FYStart, FYEnd, seq)) %>%
  unnest(VolFY)

#     ID Volunteership FYStart FYEnd VolFY
#  <int> <chr>           <int> <int> <int>
#1     1 Fabulousness     2019  2021  2019
#2     1 Fabulousness     2019  2021  2020
#3     1 Fabulousness     2019  2021  2021
#4     2 Graciousness     2021  2021  2021
#5     3 Loveliness       1995  1999  1995
#6     3 Loveliness       1995  1999  1996
#7     3 Loveliness       1995  1999  1997
#8     3 Loveliness       1995  1999  1998
#9     3 Loveliness       1995  1999  1999

试试这个:

newdat <- do.call(rbind, Map(function(ID, S, E) data.frame(ID=ID, VolFY=seq(S, E)), dat$ID, dat$FYStart, dat$FYEnd))
merge(dat, newdat, by = "ID")
#   ID Volunteership FYStart FYEnd VolFY
# 1  1  Fabulousness    2019  2021  2019
# 2  1  Fabulousness    2019  2021  2020
# 3  1  Fabulousness    2019  2021  2021
# 4  2  Graciousness    2021  2021  2021
# 5  3    Loveliness    1995  1999  1995
# 6  3    Loveliness    1995  1999  1996
# 7  3    Loveliness    1995  1999  1997
# 8  3    Loveliness    1995  1999  1998
# 9  3    Loveliness    1995  1999  1999

这是可行的,因为我们首先遍历每一行并生成一个仅包含新年的迷你帧(在 merge返回原始数据之前):

Map(function(ID, S, E) data.frame(ID=ID, VolFY=seq(S, E)), dat$ID, dat$FYStart, dat$FYEnd)
# [[1]]
#   ID VolFY
# 1  1  2019
# 2  1  2020
# 3  1  2021
# [[2]]
#   ID VolFY
# 1  2  2021
# [[3]]
#   ID VolFY
# 1  3  1995
# 2  3  1996
# 3  3  1997
# 4  3  1998
# 5  3  1999

数据

dat <- structure(list(ID = 1:3, Volunteership = c("Fabulousness", "Graciousness", "Loveliness"), FYStart = c(2019L, 2021L, 1995L), FYEnd = c(2021L, 2021L, 1999L)), class = "data.frame", row.names = c(NA, -3L))