Search code examples
rggplot2labelmelt

ggplot labels for melted dataframes


It's often the case I melt my dataframes to show multiple variables on one barplot. The goal is to create a geom_bar with one par for each variable, and one summary label for each bar.

For example, I'll do this:

mtcars$id<-rownames(mtcars)
tt<-melt(mtcars,id.vars = "id",measure.vars = c("cyl","vs","carb"))
ggplot(tt,aes(variable,value))+geom_bar(stat="identity")+
    geom_text(aes(label=value),color='blue')

The result is a barplot in which the label for each bar is repeated for each case (it seems): overlapping labels

What I want to have is one label for each bar, like this:

enter image description here

A common solution is to create aggregated values to place on the graph, like this:

aggr<-tt %>% group_by(variable) %>% summarise(aggrLABEL=mean(value))

ggplot(tt,aes(variable,value))+geom_bar(stat="identity")+
    geom_text(aes(label=aggr$aggrLABEL),color='blue')

or

ggplot(tt,aes(variable,value))+geom_bar(stat="identity")+
    geom_text(label=dplyr::distinct(tt,value),color='blue')

However, these attempts result in errors, respectively:

For solution 1: Error: Aesthetics must be either length 1 or the same as the data (96): label, x, y

For solution 2: Error in [<-.data.frame(*tmp*, aes_params, value = list(label = list( : replacement element 1 is a matrix/data frame of 7 rows, need 96

So, what to do? Setting geom_text to stat="identity" does not help either.


Solution

  • What I would do is create another dataframe with the summary values of your columns. I would then refer to that dataframe in the geom_text line. Like this:

    library(tidyverse) # need this for the %>%
    
    tt_summary <- tt %>%
     group_by(variable) %>%
     summarize(total = sum(value))
    
    ggplot(tt, aes(variable, value)) +
    geom_col() +
    geom_text(data = tt_summary, aes(label = total, y = total), nudge_y = 1) # using nudge_y bc it looks better.
    

    enter image description here