Reputation: 10340
I am trying to create a bar plot with two font faces for the y labels (don't confuse: it's called x due to coord_flip()
).
However, I have not found any solution for this on the internet.
Is it even possible?
I've got this so far.
library(ggplot2)
labs <- paste(rep("1st", 40), rep("2nd", 40), rep("3rd", 40))
labs <- strsplit(labs, " ")
v1 <- ggplot(data.frame(x = 1:40, y = 1:40), aes(x,y)) +
geom_bar(stat = "identity", fill = "grey50") +
coord_flip() +
scale_x_discrete(labels = paste(sapply(labs, "[[", 1),
.(bold(.(sapply(labs, "[[", 2)))),
sapply(labs, "[[", 3)),
breaks = 1:40)
v1
I want to be the 2nd
in all ylabs as bold face.
Yet, I get this:
The tick labels should look like this ([=====] indicate the bars in the plot):
1st 2nd 3rd [================================]
1st 2nd 3rd [=============================]
1st 2nd 3rd [==========================]
...
Upvotes: 2
Views: 1295
Reputation: 558
You have to define an expression
.
library(ggplot2)
all.data <- data.frame(group=c('a','b'),count=c(5,8))
ggplot(data=all.data, aes(group, count)) +
geom_bar(stat = "identity") +
scale_x_discrete(label=c( expression(paste("xxx",bold("foo"))), expression(paste("yyy",bold("bar"))) ))
A post here on stackoverflow got me on the right track: Use expression with a variable r
labs <- paste(rep("1st", 40), rep("2nd", 40), rep("3rd", 40))
labs <- strsplit(labs, " ")
# create a vector of expressions
# everything in .() is evaluated and ~ forms an expression
plot.labs <- bquote( .(labs[[1]][1]) ~ bold(.(labs[[1]][2])) ~ .(labs[[1]][3]))
# produce a list of expressions
plot.labs.apply <- lapply(labs, function(x) {plot.labs <- bquote( .(x[1]) ~ bold(.(x[2])) ~ .(x[3]))})
# was it done correctly?
class(plot.labs.apply[[2]])
# i used a smaller data frame to not overload the plot
ggplot(data.frame(x = c('a','b'), y = c(40,25)), aes(x,y)) +
geom_bar(stat = "identity", fill = "grey50") +
coord_flip() +
scale_x_discrete(label = c(plot.labs.apply) )
Upvotes: 2
Reputation: 558
You need to change the axis.text.x instead of working directly on the scale.x.discrete.
As a side comment to create your labs
vector, you can use:
labs <- rep( c("1st","2nd","3rd"), 40)
font.faces <- rep( c("plain","bold","plain"), 40 )
The bold/plain face can be done like this:
library(ggplot2)
# have some example data
all.data <- data.frame(group=c('a','b'),count=c(5,8))
ggplot(data=all.data, aes(group, count)) +
geom_bar(stat = "identity") +
# put your names here
scale_x_discrete(label=c("foo","bar")) +
# put a vector assigning bold and plain here
# e.g. you can put font.faces vector here if you have 40 labels
theme( axis.text.x = element_text(face=c("bold","plain")) )
A more explicit example would be this one. Please make sure that the error about unequal amounts of elements in your ggplot statement does not result from the fact that your sample naming on the x-axis (y-axis after flipping) are repetitive. They may need to be unique.
# generate some data
all.data <- as.data.frame(matrix(seq(30), nrow = 30, ncol = 1))
# produce labels and font faces
# labels need to be unique to make sure ggplot2 doesn't summarise the categories
labs <- rep( c("1st","2nd","3rd"), 10)
labs.ext <- paste(labs, rep(seq(10), each=3), sep='_')
font.faces <- rep( c("plain", "bold", "plain"), 10)
# add a label column to the data frame (and make sure that it will be a factor with levels in your intended order)
all.data[,2] <- factor(labs.ext, levels = labs.ext)
colnames(all.data) <- c("count","name")
# including your coord_flip(), x axis transforms to y axis
ggplot(data=all.data, aes(name, count)) + geom_bar(stat='identity') + theme(axis.text.y = element_text(face = font.faces)) + coord_flip()
Upvotes: 0