1

I was not able to properly color groups in a time series. It looks like the order got messed up. Example code is below. Any hints?

library(ggplot2)

getSeason <- function(DATES) {
#found here https://stackoverflow.com/questions/9500114/find-which-season-a-particular-date-belongs-to
WS <- as.Date("2012-12-15", format = "%Y-%m-%d") # Winter Solstice
SE <- as.Date("2012-3-15",  format = "%Y-%m-%d") # Spring Equinox
SS <- as.Date("2012-6-15",  format = "%Y-%m-%d") # Summer Solstice
FE <- as.Date("2012-9-15",  format = "%Y-%m-%d") # Fall Equinox

# Convert dates from any year to 2012 dates
d <- as.Date(strftime(DATES, format="2012-%m-%d"))

ifelse (d >= WS | d < SE, "Winter",
  ifelse (d >= SE & d < SS, "Spring",
    ifelse (d >= SS & d < FE, "Summer", "Fall")))
}

zz <- sample(1:10000,365)/1000
dag <- seq(as.Date("2014-01-01"), as.Date("2014-12-31"), by = "day")
seas <-  getSeason(dag)
test <- data.frame(zz,dag,seas)

ggplot(data=test, aes(x=dag,ymax=zz,ymin=0,fill=seas))+
geom_ribbon()

enter image description here

mpalanco
  • 12,960
  • 2
  • 59
  • 67
Krisselack
  • 503
  • 3
  • 16

4 Answers4

2

I ran this to test your data and it looks like your winter is in both end of your data which results in 2014-03-14 Winter connecting to 2014-12-15 Winter across all the other seasons.

ggplot(test, aes(dag)) + 
   geom_ribbon(aes(ymin = zz - 1, ymax = zz + 1), fill = "grey70") +
   geom_line(aes(y = zz, group = seas)) + facet_grid(. ~ seas)

enter image description here

you can also see it here,

ggplot(test, aes(x= dag, y= zz)) +
geom_line(aes(colour= seas)) +
geom_ribbon(aes(ymax= zz, ymin= zz, fill= seas), alpha = 0.2) 

ddd

a possible solution could be to subset your data like this,

ggplot() + 
 geom_line(data=subset(test, dag < as.Date("2014-12-15") ), aes(dag,zz,colour=seas))  + 
 geom_line(data=subset(test, dag > as.Date("2014-12-15") ), aes(dag,zz,colour=seas)) 

d

uT5r
  • 156
  • 6
  • I'd edit the `ifelse()` to assign two different winter variables, `Winter2014` and `Winter2015`, then use `scale_colour_manual()` to color both winters with the same color although they are different groups. – qdread Jan 25 '18 at 12:47
  • Glad you found a solution. You should add it as an answer or possible add it into what I have posted so that other user can benefit some your solution. – uT5r Jan 25 '18 at 12:55
2

You can solve it by subsetting your data in two, above and below WS, and plotting two geom_ribbon. Thus you convert the continuous WS series into two discrete sections.

library(dplyr)
ggplot() +
  geom_ribbon(data = filter(test, dag >= "2014-12-15") ,
              aes(x = dag, ymax = zz, ymin = 0, fill = seas)) +
  geom_ribbon(data = filter(test, dag < "2014-12-15") ,
              aes(x = dag, ymax = zz, ymin = 0, fill = seas))

enter image description here

mpalanco
  • 12,960
  • 2
  • 59
  • 67
1

Here is a general solution that requires the lubridate package. It also does not require the difficult-to-read ifelse() syntax, instead using cut() to split the vector of dates into factor levels corresponding to each of the seasons.

Function to return a character vector of seasons given dates

getSeason <- function(DATES) {
  require(lubridate)

  # Get day of year of solstices
  solstices <- as.Date(c('3-15','6-15','9-15','12-15'),format = '%m-%d')
  solstice_day <- yday(solstices)

  # get year and day of year of dates
  dates_year <- year(DATES)
  dates_day <- yday(DATES)

  # Split dates vector into seasons
  season_label <- as.character(cut(dates_day, 
                                   breaks = c(0,solstice_day,367), 
                                   labels = c('winter','spring','summer','fall','winter_next')))

  # Deal with the second winter
  dates_year[season_label == 'winter_next'] <- dates_year[season_label == 'winter_next'] + 1
  season_label[season_label == 'winter_next'] <- 'winter'

  # Return seasons pasted with year
  paste0(season_label, dates_year)

}

Code to plot ribbon

library(ggplot2)
zz <- sample(1:10000,365)/1000
dag <- seq(as.Date("2014-01-01"), as.Date("2014-12-31"), by = "day")
seas <-  getSeason(dag)
test <- data.frame(zz,dag,seas)

ggplot(data=test, aes(x=dag,ymax=zz,ymin=0,fill=seas))+
  geom_ribbon() +
  scale_fill_manual(values = c('winter2014'='red','spring2014'='blue','summer2014'='green','fall2014'='yellow','winter2015'='red'))

Result

season ribbon

qdread
  • 3,389
  • 19
  • 36
1

You can add a dummy missing value somewhere between the two winters:

test[nrow(test), ] <- list(NA, as.Date("2014-6-1"), "Winter")

ggplot(data=test, aes(x=dag,ymax=zz,ymin=0,fill=seas))+
  geom_ribbon()

enter image description here

alko989
  • 7,688
  • 5
  • 39
  • 62
  • Thank you all! I was able to solve it by manually cutting the data (which statements) and adding them as yearly ribbons. My actual time series was longer than the example provided. – Krisselack Jan 26 '18 at 13:51