Автоматизировать mutate() и case_when() для каждого значения в dplyr

У меня есть фрейм данных с именем «данные», который содержит столбец «дата», в котором указана дата события.

Я хочу добавить столбец, описывающий рассматриваемый «зимний сезон» (фактически период между августом одного года и августом другого года).

Для этого я делаю мутацию, которая берет дату и с case_when возвращает строку, соответствующую рассматриваемой зиме.

Например, если для данной строки указана дата 12 декабря 2017 года, блок кода заполнит новый столбец «зимний сезон» строкой «зима 2017-2018».

Это работает очень хорошо, но мой код тяжелый, и это заставило меня делать это вручную, ситуация за ситуацией. Я чувствую, что это можно упростить более элегантным способом и адаптировать к любому году. Что между первым августа года X и первым августа года Y он возвращает значение «зима 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"
  ))

Можете ли вы предоставить некоторые из ваших данных через dput? Вы можете сделать dput(head(data)), а затем вставить результат в свой вопрос.

AndrewGB 16.05.2022 00:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
45
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

минимальный воспроизводимый пример значительно облегчит понимание проблемы, но, возможно, это поможет:

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

Created on 2022-05-16 by the reprex package (v2.0.1)

Ответ принят как подходящий

Вы можете рассчитать месяц и год от вашей даты. Тогда, если месяц < 8 (до августа), то зима от года-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)
          

Другие вопросы по теме