Reputation: 8626
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:
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
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)])
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