Dumbbell plot with out of bounds values (dates)

Viewed 30

I am trying to replicate the following example and to build a dumbbell plot: r graph gallery.

The idea is to plot migration beginning and end dates for migratory fish. In y I have fish species and lifestages and in x I have the julian day.

It works relatively well so far, except for some of my species, for which the beginning of the migration is actually at the end of the year N and it ends at the beggining of the following year N+1. For instance, silver eels starts to migrate in autumn and finnishes in the end of march.

What I would like to get in such cases, would be to have a segment from my beginning date to the end of the year, and the other section starting on january 1st to my end of migration.

Instead, ggplot switches the two dates and I end up with one segment on the part of the year were there actually is no migration...

Here is the code I am using:

First I build my dataframe and prepare my data:

sp_stade <- c(rep("TRM - smolts",2), rep("TRM - adultes",2), rep("TRM - post-frai",2), rep("SAT - smolts",2), rep("SAT - adultes",2), rep("SAT - post-frai",2), rep("ANG - civelles",2), rep("ANG - anguilles jaunes",2), rep("ANG - anguilles argentees",2), rep("LPR - juveniles",2), rep("LPR - adultes",2), rep("LPM - juveniles",2), rep("LPM - adultes",2))

deb_fin <- rep(c("debut", "fin"), 13)

valeur <- c(69, 133, 140, 326, 338, 96, 88, 132, 137, 331, 344, 58, 10, 145, 148, 275, 213, 90, 213, 120, 244, 151, 305, 151, 335, 181)


table_fin <- data.frame(sp_stade,
        deb_fin, 
        valeur, 
        stringsAsFactors=FALSE) 

debut <- table_fin %>%
        filter(deb_fin == "debut")
fin <- table_fin %>%
        filter(deb_fin == "fin")
head(fin)

Then the plot:

p <- ggplot(table_fin)+     
        geom_segment(data = debut,
                aes(x = as.Date(valeur, origin = as.Date("01/01", "%d/%m")), y = sp_stade,
                        yend = fin$sp_stade, xend = as.Date(fin$valeur, origin = as.Date("01/01", "%d/%m"))), 
                color = "#aeb6bf",
                size = 4.5, 
                alpha = .5) +
        scale_x_date(date_breaks = "2 weeks", date_labels = "%d/%m")+
        geom_point(aes(x = as.Date(valeur, origin = as.Date("01/01", "%d/%m")), y = sp_stade, color = deb_fin), size = 4, show.legend = TRUE)
p

I end up with this: dumbbell plot

As you can see from the differing colors of the beginning and end dots, the segment that is built is not what I expect for "TRM/SAT - post-frai" or the two "LPR" and "LPM" or "anguilles argentees"...

Any help would be greatly appreciated! Thx!

1 Answers

To make plotting easier, I would combine the two data frames so we have start and finish times

df <- debut[1]
df$debut_valeur <- debut$valeur
df$fin_valeur   <- fin$valeur

Now we can convert the days into dates of an arbitrary non-leap year:

df$fin_valeur   <- as.Date("2021-01-01") + df$fin_valeur - 1
df$debut_valeur <- as.Date("2021-01-01") + df$debut_valeur - 1

If the end values are less than the starting values, subtract a year from the start times:

wrong <- df$fin_valeur < df$debut_valeur
df$debut_valeur[wrong] <- df$debut_valeur[wrong] - 365

Now our plotting code is straightforward:

ggplot(df, aes(debut_valeur, sp_stade)) +
  geom_segment(aes(xend = fin_valeur, yend = sp_stade), size = 4.5,
               alpha = 0.1) +
  geom_point(color = "#762a83", size = 4.5) +
  geom_point(aes(x = fin_valeur), color = "#009688", size = 4.5) +
  theme_light(base_size = 16) +
  scale_x_date(date_labels = "%d %b", name = NULL) +
  theme(axis.line = element_blank(),
        axis.ticks.y = element_blank(),
        panel.border = element_blank(),
        panel.grid.major.y = element_blank(),
        axis.title.y = element_blank())

enter image description here

Related