为 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)
我有一个名为“数据”的数据框,其中包含给出事件日期的“日期”列。
我想添加一个列来描述正在考虑的“冬季”(实际上是一年的八月和另一年的八月之间的时间段)。
为此,我做了一个变异,它接受日期和 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)