Search code examples
rggplot2geom-barstacked

Is there a possibility to combine position_stack and nudge_x in a stacked bar chart in ggplot2?


I want to add labels to a stacked bar chart to achieve something like this:

enter image description here

The goal is simple: I need to show market shares and changes versus previous year in the same graph. In theory, I would just add "nudge_x=0.5," to geom_text in the code but I get the error: "Specify either position or nudge_x/nudge_y". Is it possible to use some workaround, maybe another package? Thanks a lot in advance!

Code:

        DashboardCategoryText <- c("Total Market","Small Bites","Bars","Total Market","Small Bites","Bars","Total Market","Small Bites","Bars")
    Manufacturer <- c("Ferrero","Ferrero","Ferrero","Rest","Rest","Rest","Kraft","Kraft","Kraft")
    MAT <- c(-1,5,-7,6,8,10,-10,5,8)
    Measure_MATCurrent <- c(500,700,200,1000,600,80,30,60,100)

    data <- data.frame(DashboardCategoryText,Manufacturer,MAT,Measure_MATCurrent)

    library(dplyr)
    groupedresult <- group_by(data,DashboardCategoryText)
    groupedresult <- summarize(groupedresult,SUM=sum(Measure_MATCurrent))
    groupedresult <- as.data.frame(groupedresult)

    data <- merge(data,groupedresult,by="DashboardCategoryText")

    data$percent <- data$Measure_MATCurrent/data$SUM

    library(ggplot2)

    ggplot(data, aes(x=reorder(DashboardCategoryText, SUM), y=percent, fill=Manufacturer)) +
          geom_bar(stat = "identity", width = .7, colour="black", lwd=0.1) +
          geom_text(aes(label=ifelse(percent >= 0.005, paste0(sprintf("%.0f", percent*100),"%"),"")),
          position=position_stack(vjust=0.5), colour="white") +
          geom_text(aes(label=MAT,y=percent),
          nudge_x=0.5,
          position=position_stack(vjust=0.8),
          colour="black") +
          coord_flip() +
          scale_y_continuous(labels = percent_format()) +
          labs(y="", x="")

Solution

  • I have a somewhat 'hacky' solution where you essentially just change the geom_text data in the underlying ggplot object before you plot it.

    p <- ggplot(data, aes(x=reorder(DashboardCategoryText, SUM), y=percent, fill=Manufacturer)) +
        geom_bar(stat = "identity", width = .7, colour="black", lwd=0.1) +
        geom_text(aes(label=ifelse(percent >= 0.005, paste0(sprintf("%.0f", percent*100),"%"),"")),
                  position=position_stack(vjust=0.5), colour="white") +
        geom_text(aes(label=MAT,y=percent),
                  position=position_stack(vjust=.5),
                  colour="black") +
        coord_flip() +
        scale_y_continuous(labels = percent_format()) +
        labs(y="", x="")
    
    q <- ggplot_build(p)  # get the ggplot data
    q$data[[3]]$x <- q$data[[3]]$x + 0.5  # change it to adjust the x position of geom_text
    plot(ggplot_gtable(q))  # plot everything
    

    plot