ggplot dismisses x axis factor levels

Viewed 208

I have the following issue: if I run the code, my labels for the X axis loose for some unknown reason the assigned factor levels and instead of order: 1 week, 2 week it becomes: 1 week, 10 week... when I use geom_line AND geom_point:

datax <- read.csv("https://raw.githubusercontent.com/justasmundeikis/stackoverflow/main/example.csv")
df <- datax %>%
        select(2,4,5,7,8,10,11,14,15)%>%
        rename(week_nr=savaites_mirusiuju_label.en,
               county_c=apskritysLR,
               county=apskritysLR_label.en,
               age_group_c=amzius_mirusiuju,
               age_group=amzius_mirusiuju_label.en,
               sex_c=Lytis,
               sex=Lytis_label.en,
               year=LAIKOTARPIS,
               values=obsValue)%>%
        filter(age_group!="Not indicated")%>%
        mutate(week_nr=factor(week_nr,
                        levels=paste(1:53, "week")))


x <- df %>%
        filter(age_group=="25–29",
               sex_c==0,
               county_c=="00")%>%
        group_by(year, week_nr)%>%
        summarise(values=sum(values))%>%
        mutate(cat=as.factor(ifelse(year>=2020,1,0)))

ggplot(x,aes(x=week_nr, values, group=year))+
        geom_line(data = x%>%filter(cat==1), col="red")+
        geom_point(data = x%>%filter(cat==0), col="grey")+
        theme(axis.text.x = element_text(angle = 90, hjust = 1))

... but if I run the last chunk without geom_line

ggplot(x,aes(x=week_nr, values, group=year))+
        #geom_line(data = x%>%filter(cat==1), col="red")+
        geom_point(data = x%>%filter(cat==0), col="grey")+
        theme(axis.text.x = element_text(angle = 90, hjust = 1))

then the axis label order is correct. My main goal is to have grey point for all years, but 2020. For 2020 I want to have a red line, therefore i create the cat factor variable.

How could I solve this? Thanks in advance

2 Answers

This is made more difficult by your weeks being factors rather than numbers from 1 to 53 (you could always make the x axis numeric and label it with text which would fix the problem). Anyway, the reason this reordering is happening is because not all the factor levels of week_nr appear in the subset cat == "1". The unused factor levels are dropped, which triggers a re-ordering. There are a couple ways to fix this:

  1. Add scale_x_discrete(drop = FALSE)
  2. Move the geom_point call before the geom_line call, since the dataset used for the first geom drawn determines the levels that are used.
ggplot(x, aes(week_nr, values, group = year)) +
  geom_line(data = x %>% filter(cat == "1"), color = "red") +
  geom_point(data = x %>% filter(cat == "0"), color = "grey") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  scale_x_discrete(drop = FALSE)

enter image description here

Not sure about what exactly is the issue and what happens under the hood ... but you can solve your issue by plotting the geom_point first and the geom_line second. I can only guess that the reason is that not all levels of your factor week_nr are present in both datasets ...

library(dplyr)
library(ggplot2)

datax <- read.csv("https://raw.githubusercontent.com/justasmundeikis/stackoverflow/main/example.csv")
df <- datax %>%
  select(2,4,5,7,8,10,11,14,15)%>%
  rename(week_nr=savaites_mirusiuju_label.en,
         county_c=apskritysLR,
         county=apskritysLR_label.en,
         age_group_c=amzius_mirusiuju,
         age_group=amzius_mirusiuju_label.en,
         sex_c=Lytis,
         sex=Lytis_label.en,
         year=LAIKOTARPIS,
         values=obsValue)%>%
  filter(age_group!="Not indicated") %>% 
  mutate(week_nr=factor(week_nr,
                         levels=paste(1:53, "week")))

x <- df %>%
  filter(age_group=="25–29",
         sex_c==0,
         county_c=="00")%>%
  group_by(year, week_nr)%>%
  summarise(values=sum(values))%>%
  ungroup() %>% 
  mutate(cat=ifelse(year>=2020,1,0))
#> `summarise()` regrouping output by 'year' (override with `.groups` argument)

ggplot(x,aes(x=week_nr, values, group=year))+
  geom_point(data = x%>%filter(cat==0), col="grey")+
  geom_line(data = x%>%filter(cat==1), col="red")+
  theme(axis.text.x = element_text(angle = 90, hjust = 1))
#> Warning: Removed 2 rows containing missing values (geom_point).

Related