Search code examples
rggplot2categorical-data

Add line to stacked barchart with categorical x-axis


I'm trying to add a geom_line to this plot but no luck.

enter image description here

This might have worked if not the x-axis are of categorical type (chr). I'm trying this with no effect: geom_line(aes(y=nettoforandring_mellan_ar_1_och_2, group=arsintervall)) where nettoforandring_mellan_ar_1_och_2 is my col. with the netto of the stacked bars for each categorical yr, and arsintervall is the categorical x-axis.

-> any ideas?

Thanks!


Solution

  • OP, please add a Reproducible Example in the future (data and full code which alone can produce an example plot that showcases your problem). However, the core question relates to adding geom_line() across a categorical (discrete) x axis.

    REPRODUCIBLE EXAMPLE

    I can recreate the same sort of question using mtcars:

    library(ggplot2)
    
    p <-
      ggplot(mtcars, aes(x=factor(gear), y=wt)) +
      geom_col(aes(fill=factor(cyl)))
    

    enter image description here

    SOLUTION

    Since categorical (discrete) axes aren't "connected", ggplot2 will not by default draw a line between values on the x axis. It treats any line drawn as being connected only by y values. Therefore, you get vertical lines only when you do this:

    p + geom_line(linewidth=0.8)
    

    enter image description here

    To connect across x axis values, you have to "force" the connection by telling ggplot2 to put all the points into the same group. Do this via mapping group=1 or group= literally any random string, value, etc.

    p + geom_line(aes(group=1), linewidth=0.8)
    

    enter image description here

    While unnecessary here, if you wanted to only draw a line with something like average values (often the case when wanting to draw a line across stacked barplots), you can use stat_summary(geom="line") and apply the same logic. The code below produces a line that only connects y value points which are the mean for each x position.

    p + stat_summary(
        aes(group="big scary monster"),  # see how group can equal anything here?
        geom="line", linewidth=0.8)
    

    enter image description here