为 dplyr 中的每个值自动执行 mutate() 和 case_when()

Automate mutate() and case_when() for each value in dplyr

我有一个名为“数据”的数据框,其中包含给出事件日期的“日期”列。

我想添加一个列来描述正在考虑的“冬季”(实际上是一年的八月和另一年的八月之间的时间段)。

为此,我做了一个变异,它接受日期和 case_when returns 对应于所考虑的冬天的字符串。

例如,如果给定行的日期是 2017 年 12 月 12 日,代码块将使用字符串“winter 2017-2018”填充新列“winter season”。

这很好用,但我的代码很重,这迫使我根据情况手动完成。我觉得这可以以更优雅的方式简化并适应任何年份。在 X 年 8 月 1 日和 Y 年 8 月 1 日之间,returns 值“winter x-y”?

如何更高效地编写这段代码?

data <- data %>%
  mutate(winter = case_when(
    between(date, as.Date("2013-08-01"), as.Date("2014-08-01")) == TRUE ~ "winter 2013-2014",
    between(date, as.Date("2014-08-01"), as.Date("2015-08-01")) == TRUE ~ "winter 2014-2015",
    between(date, as.Date("2015-08-01"), as.Date("2016-08-01")) == TRUE ~ "winter 2015-2016",
    between(date, as.Date("2016-08-01"), as.Date("2017-08-01")) == TRUE ~ "winter 2016-2017",
    between(date, as.Date("2017-08-01"), as.Date("2018-08-01")) == TRUE ~ "winter 2017-2018",
    between(date, as.Date("2018-08-01"), as.Date("2019-08-01")) == TRUE ~ "winter 2018-2019",
    between(date, as.Date("2019-08-01"), as.Date("2020-08-01")) == TRUE ~ "winter 2019-2020",
    between(date, as.Date("2020-08-01"), as.Date("2021-08-01")) == TRUE ~ "winter 2020-2021",
    between(date, as.Date("2021-08-01"), as.Date("2022-08-01")) == TRUE ~ "winter 2021-2022",
    between(date, as.Date("2022-08-01"), as.Date("2023-08-01")) == TRUE ~ "winter 2022-2023",
    TRUE ~ "autre"
  ))

A minimal reproducible example 会使问题更容易理解,但也许这会有所帮助:

library(tidyverse)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union

data <- data.frame(name = 1:100,
                   date = seq.Date(from = as.Date("2013-08-01"),
                                   to = as.Date("2022-08-01"),
                                   length.out = 100))

data %>%
  mutate(season = case_when(quarter(date, fiscal_start = 0) == 1 ~ "Summer",
                            quarter(date, fiscal_start = 0) == 2 ~ "Autumn",
                            quarter(date, fiscal_start = 0) == 3 ~ "Winter",
                            quarter(date, fiscal_start = 0) == 4 ~ "Spring"),
         year = paste(year(date) - 1, year(date), sep = "-")) %>%
  unite("season_and_year", c(season, year), sep = " ", remove = TRUE) %>%
  head()
#>   name       date  season_and_year
#> 1    1 2013-08-01 Winter 2012-2013
#> 2    2 2013-09-03 Spring 2012-2013
#> 3    3 2013-10-06 Spring 2012-2013
#> 4    4 2013-11-08 Spring 2012-2013
#> 5    5 2013-12-11 Summer 2012-2013
#> 6    6 2014-01-14 Summer 2013-2014

reprex package (v2.0.1)

于 2022-05-16 创建

您可以根据日期计算月份和年份。那么如果月 < 8(8 月之前),那么冬天是从第 1 年到第 1 年。否则冬天就是年复一年+1

data <- data %>%
   mutate(
          month=as.numeric(format(date,"%m")),
          year=as.numeric(format(date,"%Y")),
          winter=case_when(month<8 ~ paste0("Winter ",year-1,"-",year),
                           TRUE ~ paste0("Winter ",year,"-",year+1))
          ) %>%
    select(-month,-year)