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))
我在 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))