Vasily A
Vasily A

Reputation: 8626

customize categorical axis labels (allowing duplicated labels) in ggplot

I want to build a plot based on a dataframe with categorical X axis and multiple types of elements to draw, and only certain records are supposed to be placed on the plot:

dt1 <- fread('
    ID label   type value
    a1     A    bar   40 
    a1     A  point   30 
    b1     B    bar   50 
    b1     B  point   20 
    c1     C    bar   30 
    c1     C  point   45 
    c1     C  point   20 
    d1     D  point   30 
    d1     D  point   35 
    e1     E   none   50 
    a2     A    bar   45 
    a2     A  point   30 
    ')

# I want some custom order on the plot,
# here it will be   b1 - c1 - a1 - d1 - a2
dt1[, ID:=factor(ID, levels=unique(ID[order(value)]))]

(in this sample dataset I show only "point" and "bar" but in the real one I have more elements and additional columns used to decide whether to plot them)

The plot I want should be something like this: desired result
You can see that labels are taken from another column in my dataframe, but they are not unique, so I can't simply use aes(x=label). I guess I should add something like scale_x_discrete(labels=???) but not sure what should I put there.
In general, I am actually interested in two different types of solution: a) map labels to another column of the original dataset; b) somehow extract "internal" labels from the ggplot object and process them with simple things like gsub(), toupper() etc.

Upvotes: 0

Views: 1040

Answers (1)

lroha
lroha

Reputation: 34406

You can pass a function to the labels argument of scale_x_discrete():

library(ggplot2)
library(data.table)

dt2 <- dt1[type != "none"]
dt2[, ID:=factor(ID, levels=unique(ID[order(value)]))]

ggplot(dt2, aes(x=ID,y=value))+
  geom_col(data=dt1[type=='bar',], alpha=0.5) +
  geom_point(data=dt1[type=='point',], size=5, col='red') +
  scale_x_discrete(limits = levels(dt2$ID), labels = function(x) dt2$label[match(x, dt2$ID)])

enter image description here

To answer your second point, given the current values of the x axis, you could also use something like:

scale_x_discrete(limits = levels(dt2$ID), labels = function(x) gsub("[[:digit:]]", "", toupper(x)))

Upvotes: 1

Related Questions