JackWassik
JackWassik

Reputation: 75

Changing months to seasons

I am working in R. I have a dataframe where I have sampling date, the month of that sampling date in full name, and water temperature. Below is a sample of my data frame.

   Date           Month       Temperature
   2016-07-01     July        13
   2017-01-08     January     5
   2018-09-19     September   11
   2019-10-24     October     9

What I want to do is use the month and create a new column in which the season is labeled. For the purposes of this project I am classifying Jan-Mar as Winter, Apr-Jun as Spring, Jul-Sep as Summer, Oct-Dec as Fall.

Upvotes: 2

Views: 1976

Answers (3)

G. Grothendieck
G. Grothendieck

Reputation: 269654

Assume the input shown reproducibly in the Note at the end where the Date field is of class Date -- convert it as shown in the Note if not. The following then shows a variety of approaches. The first two convert the Date column (which seems easier) and the last two convert the Month column.

1) yearqtr Convert Date to a yearqtr object. Using cycle on that will give the quarter (1, 2, 3 or 4) and then we can index the quarter number into seasons.

library(zoo)

seasons <- c("Winter", "Spring", "Summer", "Fall")
transform(DF, Season = seasons[cycle(as.yearqtr(Date))])
##         Date     Month Temperature Season
## 1 2016-07-01      July          13 Summer
## 2 2017-01-08   January           5 Winter
## 3 2018-09-19 September          11 Summer
## 4 2019-10-24   October           9   Fall

If just using the quarter number is ok then this one-liner would be sufficient.

transform(DF, Season = cycle(as.yearqtr(Date)))

2) quarters We can also do it using only base R by using the quarters function which returns Q1, Q2, Q3 or Q4 as a string given a date. In that case we need to ensure that Seasons.Q uses those names in order to use it to do a lookup.

Seasons.Q <- c(Q1 = "Winter", Q2 = "Spring", Q3 = "Summer", Q4 = "Fall")
transform(DF, Season = Seasons.Q[quarters(Date)])

If using Q1, Q2, Q3, Q4 instead of the names is ok then we could reduce it to this one-liner:

transform(DF, Season = quarters(Date))

3) match The above used the Date field. We can also use the Month field as our input converting it to a month number 1, 2, 3, ..., 12 and then converting that to a quarter number which can be indexed into seasons defined above.

transform(DF, Season = seasons[(match(Month, month.name) - 1) %/% 3 + 1])

If a quarter number rather than season name is sufficient then we can reduce it to this one-liner:

transform(DF, Season = (match(DF$Month, month.name) - 1) %/% 3 + 1)

4) Date formatting We can also use Date formatting to convert the Month to a Date and then use quarters and a lookup into Seasons.Q.

transform(DF, Season = Seasons.Q[quarters(as.Date(paste(DF$Month, "001"), "%B %y%d"))])

Note

Lines <- "
 Date           Month       Temperature
   2016-07-01     July        13
   2017-01-08     January     5
   2018-09-19     September   11
   2019-10-24     October     9"
DF <- read.table(text = Lines, header = TRUE)
DF$Date <- as.Date(DF$Date)

Upvotes: 0

MarBlo
MarBlo

Reputation: 4524

You can do this like so:

library(tidyverse)
library(lubridate)

df %>% 
  mutate(season = lubridate::quarter(Date)) %>% 
  mutate(season = case_when(
    season == 1 ~ 'Winter',
    season == 2 ~ 'Spring',
    season == 3 ~ 'Summer',
    season == 4 ~ 'Fall'
  ))
#>         Date     Month Temperature season
#> 1 2016-07-01      July          13 Summer
#> 2 2017-01-08   January           5 Winter
#> 3 2018-09-19 September          11 Summer
#> 4 2019-10-24   October           9   Fall

or with one line less:

df %>% 
  mutate(season = case_when(
    Month %in% c('January', 'February', 'March') ~ 'Winter',
    Month %in% c('April', 'May', 'June') ~ 'Sring',
    Month %in% c('August', 'September', 'July') ~ 'Summer',
    Month %in% c('October', 'November', 'December') ~ 'Fall'
  ))

Upvotes: 0

akrun
akrun

Reputation: 887148

Here is an option where we create a named vector and use that to match and replace the 'Month' to create new column

library(dplyr)
nm1 <- setNames(rep(c("Winter", "Spring", "Summer", "Fall"),
        each = 3), month.name)
df1 %>% 
    mutate(Season = nm1[Month])

-output

#         Date     Month Temperature Season
#1 2016-07-01      July          13 Summer
#2 2017-01-08   January           5 Winter
#3 2018-09-19 September          11 Summer
#4 2019-10-24   October           9   Fall

Or it can be done in base R

df1$Season = nm1[df1$Month]

data

df1 <- structure(list(Date = c("2016-07-01", "2017-01-08", "2018-09-19", 
"2019-10-24"), Month = c("July", "January", "September", "October"
), Temperature = c(13L, 5L, 11L, 9L)), class = "data.frame",
row.names = c(NA, 
-4L))

Upvotes: 0

Related Questions