我是R和编码领域的相对较新的用户,我已经搜索过并且无法解决此问题。我有以下数据:
groupid start.date end.date Status
1 2014-01-01 2017-01-01 A
1 2018-01-01 2020-01-01 D
2 2014-01-01 2017-01-01 B
如何生成一个数据框,其中每个观测值都是一年,而不是groupid和时间段的组合。
我正在寻找的输出是:
groupid year status
1 2014 A
1 2015 A
1 2016 A
1 2017 A
1 2018 D
1 2019 D
1 2020 D
2 2014 B
2 2015 B
2 2016 B
2 2017 B
我尝试了多种方法,但我认为我的最佳尝试是:
df <- df %>%
group_by(rn=row_number()) %>%
mutate(d = list(seq(start.date, end.date, by='1 year')))
%>%
unnest()
但是我知道了
Error: Each column must either be a list of vectors or a list of data frames
[d]
搜索错误并没有帮助我进一步弄清错误所在。开始日期和结束日期存储为日期。如果很重要,它们是由仅具有四位数年份数字的两个列向量生成的,因此我应用了以下代码将其更改为可用的日期格式:
df$start.date <- as.Date(ISOdate(df$from, 1, 1))
df$end.date <- as.Date(ISOdate(df$to, 1, 1))
答案 0 :(得分:0)
您快到了!根据ID和状态对数据进行分组,因为这两个变量的组合是开始和结束日期的来源。
library(tidyverse)
df <- "groupid start.date end.date Status
1 2014-01-01 2017-01-01 A
1 2018-01-01 2020-01-01 D
2 2014-01-01 2017-01-01 B" %>% read_table2()
df %>%
group_by(groupid, Status) %>%
mutate(dates = list(seq(from = start.date, to = end.date, by = "1 year"))) %>%
unnest()
#> # A tibble: 11 x 5
#> # Groups: groupid, Status [3]
#> groupid start.date end.date Status dates
#> <int> <date> <date> <chr> <date>
#> 1 1 2014-01-01 2017-01-01 A 2014-01-01
#> 2 1 2014-01-01 2017-01-01 A 2015-01-01
#> 3 1 2014-01-01 2017-01-01 A 2016-01-01
#> 4 1 2014-01-01 2017-01-01 A 2017-01-01
#> 5 1 2018-01-01 2020-01-01 D 2018-01-01
#> 6 1 2018-01-01 2020-01-01 D 2019-01-01
#> 7 1 2018-01-01 2020-01-01 D 2020-01-01
#> 8 2 2014-01-01 2017-01-01 B 2014-01-01
#> 9 2 2014-01-01 2017-01-01 B 2015-01-01
#> 10 2 2014-01-01 2017-01-01 B 2016-01-01
#> 11 2 2014-01-01 2017-01-01 B 2017-01-01
要获取所需的格式,您可以从日期序列中提取年份并删除多余的列:
df %>%
group_by(groupid, Status) %>%
mutate(dates = list(seq(from = start.date, to = end.date, by = "1 year"))) %>%
unnest() %>%
mutate(year = lubridate::year(dates)) %>%
select(groupid, year, Status)
#> # A tibble: 11 x 3
#> # Groups: groupid, Status [3]
#> groupid year Status
#> <int> <dbl> <chr>
#> 1 1 2014 A
#> 2 1 2015 A
#> 3 1 2016 A
#> 4 1 2017 A
#> 5 1 2018 D
#> 6 1 2019 D
#> 7 1 2020 D
#> 8 2 2014 B
#> 9 2 2015 B
#> 10 2 2016 B
#> 11 2 2017 B
由reprex package(v0.2.0)于2018-06-22创建。
答案 1 :(得分:0)
camille的答案基于groupid
和Status
的组合是唯一的隐式假设。但是,这不能保证。此外,OP本身已选择按行号进行分组以确保安全。
分组是必需的,因为seq()
和单个冒号运算符:
不接受vetors作为输入。
dplyr
/ tidyr
解决方案此方法按行号分组,并提取创建序列的之前年。
df1
是OP给出的小标题(请参阅下面的Data
部分)。
library(dplyr)
library(tidyr)
library(lubridate)
df1 %>%
group_by(rn = row_number()) %>%
mutate(year = list(year(start.date):year(end.date))) %>%
unnest() %>%
ungroup() %>%
select(groupid, year, Status)
# A tibble: 11 x 3 groupid year Status <int> <int> <chr> 1 1 2014 A 2 1 2015 A 3 1 2016 A 4 1 2017 A 5 1 2018 D 6 1 2019 D 7 1 2020 D 8 2 2014 B 9 2 2015 B 10 2 2016 B 11 2 2017 B
data.table
方法 data.table
允许使用更简洁的代码实现相同的结果:
library(data.table)
setDT(df1)[, .(groupid, year = year(start.date):year(end.date), Status),
by = .(rn = 1:nrow(df1))][
, rn := NULL][]
groupid year Status 1: 1 2014 A 2: 1 2015 A 3: 1 2016 A 4: 1 2017 A 5: 1 2018 D 6: 1 2019 D 7: 1 2020 D 8: 2 2014 B 9: 2 2015 B 10: 2 2016 B 11: 2 2017 B
OP公开了start.date
和end.date
是从只有四位数年份数字的两个列向量生成的。。
不必将这些年份数字预先转换为日期。它们可以直接用于创建年份序列:
library(dplyr)
library(tidyr)
df2 %>%
group_by(rn = row_number()) %>%
mutate(year = list(from:to)) %>%
unnest() %>%
ungroup() %>%
select(groupid, year, Status)
# A tibble: 11 x 3 groupid year Status <int> <int> <chr> 1 1 2014 A 2 1 2015 A 3 1 2016 A 4 1 2017 A 5 1 2018 D 6 1 2019 D 7 1 2020 D 8 2 2014 B 9 2 2015 B 10 2 2016 B 11 2 2017 B
或者,以data.table
语法:
library(data.table)
setDT(df2)[, .(groupid, year = from:to, Status), by = .(rn = 1:nrow(df2))][
, rn := NULL][]
根据help(":")
,字符参数被强制为数字,因此不需要显式强制。
df1 <- readr::read_table(
"groupid start.date end.date Status
1 2014-01-01 2017-01-01 A
1 2018-01-01 2020-01-01 D
2 2014-01-01 2017-01-01 B"
)
df2 <- readr::read_table(
"groupid from to Status
1 2014 2017 A
1 2018 2020 D
2 2014 2017 B"
)