How to assign different font faces and sizes within label text entries in ggplot2

239 views
Skip to first unread message

Aaron Polhamus

unread,
Jul 11, 2011, 12:19:12 PM7/11/11
to ggplot2
Hi all, 

I am building charts that have two lines in the axis text. The first line contains the group name, the second line contains that group population. I build my axis labels as a single character string with the format "LINE1 \n LINE2". Is it possible to assign different font faces and sizes to LINE1 and LINE2, even though they are contained within a single character string? I would like LINE1 to be large and bolded, and LINE2 to be small and unbolded.

Here's some sample code:

Treatment <- rep(c('T','C'),each=2)
Gender <- rep(c('Male','Female'),2)
Response <- sample(1:100,4)
test_df
<- data.frame(Treatment, Gender, Response)

xbreaks
<- levels(test_df$Gender)
xlabels
<- paste(xbreaks,'\n',c('POP1','POP2'))

hist
<- ggplot(test_df, aes(x=Gender, y=Response, fill=Treatment, stat="identity"))
hist
+ geom_bar(position = "dodge") + scale_y_continuous(limits = c(0,
   
100), name = "") + scale_x_discrete(labels=xlabels, breaks = xbreaks) +
    opts
(
      axis
.text.x = theme_text(face='bold',size=12)
     
)
I tried this, but the result was one large, bolded entry, and one small, unbolded entry:
hist + geom_bar(position = "dodge") + scale_y_continuous(limits = c(0, 
     
100), name = "") + scale_x_discrete(labels=xlabels, breaks = xbreaks) +
     opts
(
      axis
.text.x = theme_text(face=c('bold','plain'),size=c('15','10'))
     
)

Another possible solution is to create separate chart elements, but I don't think that ggplot2 has a 'sub-axis label' element available...

Any help would be very much appreciated.

Cheers, 

Aaron


Luciano Selzer

unread,
Jul 11, 2011, 12:55:13 PM7/11/11
to Aaron Polhamus, ggplot2
Please, don't crosspost http://stackoverflow.com/questions/6653193/different-font-faces-and-sizes-within-label-text-entries-in-ggplot2
It wastes people's time if your question has already been anwsered elsewhere.
Luciano


2011/7/11 Aaron Polhamus <aaronp...@gmail.com>
--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: http://gist.github.com/270442
 
To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

Aaron Polhamus

unread,
Jul 11, 2011, 1:01:22 PM7/11/11
to Luciano Selzer, ggplot2
True, though my reasoning was that not everybody who's a ggplot2 expert will be on StackOverflow and this list. Wasn't trying to be cheeky, as you can see from the fact that I directly imported the formatting from StackOverflow. Will wait to see if one forum is helpful next time before posting on another one. 

-A

2011/7/11 Luciano Selzer <luciano...@gmail.com>



--
Aaron Polhamus 
NASA Jet Propulsion Lab
Statistical consultant, Revolution Analytics



Luciano Selzer

unread,
Jul 11, 2011, 1:04:03 PM7/11/11
to Aaron Polhamus, ggplot2
You could also say that you are crossposting and where you are doing it so people are warned.

Cheers

Luciano Selzer

unread,
Jul 11, 2011, 1:14:24 PM7/11/11
to Aaron Polhamus, ggplot2
I was playing around ussing expressions. So at least you can bold some of the text. However, I remember that expressions don't play nice with line break. My idea was to do something like this:


xlabels <- expression(paste(bold(Female), '\n', "POP1"))
xlabels[2] <- expression(paste(bold(Male), '\n', "POP2"))


Luciano


2011/7/11 Aaron Polhamus <aaronp...@gmail.com>
Hi all, 

Aaron Polhamus

unread,
Jul 11, 2011, 1:34:23 PM7/11/11
to Luciano Selzer, ggplot2
That gets me part of the way there, thanks, Luciano. I'll give it a try here in a little bit. 

Cheers, 
Aaron 

2011/7/11 Luciano Selzer <luciano...@gmail.com>

baptiste auguie

unread,
Jul 11, 2011, 4:38:40 PM7/11/11
to Aaron Polhamus, ggplot2
Hi,

The following code combines multiple lines of plotmath expressions; I
imagine it could be adapted to work with axis labels too.

library(gridExtra)

my.title = function(expressions) {
function(...)
tableGrob(expressions, parse=TRUE,
theme=theme.list(gpar.corefill = gpar(fill = NA, col = NA),
core.just = "center"))
}

e = expression(alpha,"testing", italic(italic),
hat(beta), integral(f(x)*dx, a, b))

qplot(1,1, geom="blank") + opts(axis.title.x = my.title(e))


HTH,

baptiste

Aaron Polhamus

unread,
Jul 20, 2011, 3:17:21 AM7/20/11
to baptiste auguie, ggplot2
Dear list, 

Apologies for the long delay in following up on this conversation. Your comments and suggestions were indeed helpful. Unfortunately, after spending a fair amount of time on this problem I still haven't been able to solve it. The problem is that my group categories aren't fixed at 2 (i.e. not just fixed as 'male' and 'female'). Furthermore, within each group category I will require a variable number of population figures, depending on how many subgroups there are within each group. This suggests to me a solution where I paste together a character string which is then parsed as an expression within a chart label. 

I tried modifying Batiste's code, supplied on 11 July, as follows: 

e = as.expression('expression(alpha,bold(testing), italic(italic),
  scriptscriptstyle(bold(bold)), integral(f(x)*dx, a, b))')

qplot(1,1, geom="blank") + opts(axis.title.x = my.title(e))

but this only reads in the expression as one line, rather than as a stacked series of expressions obtained using the original 

e = expression(alpha,bold(testing), italic(italic),
  scriptscriptstyle(bold(bold)), integral(f(x)*dx, a, b))

Another approach I tried was: 

text <- paste('alpha','bold(testing)', 'italic(italic)',
  'scriptscriptstyle(bold(bold))', 'integral(f(x)*dx, a, b))',sep='\n')

qplot(1,1, geom="blank") + opts(title = text)

but I can't figure out how to evaluate those character strings as expressions. 

Any thoughts? Does my query make sense? I need a way to construct expressions statements with variable numbers of entries before evaluating them in such a way that they are stacked on top of one another within the chart legend. 

I know how nit-picky this might seem, so I apologize if I annoy anybody... 

Cheers, 
aaron 

2011/7/11 baptiste auguie <bapt...@googlemail.com>

baptiste auguie

unread,
Jul 20, 2011, 5:08:43 AM7/20/11
to Aaron Polhamus, ggplot2
Hi,


In my original example expression() was actually unnecessary,

e = c('alpha',"testing", 'italic(italic)',
'hat(beta)', 'integral(f(x)*dx, a, b)')

qplot(1,1, geom="blank") + opts(axis.title.x = my.title(e))

works as well. You can construct a vector of strings with paste, e.g.

e = paste("alpha[", 1:3, "]",sep="")


qplot(1,1, geom="blank") + opts(axis.title.x = my.title(e))

This works fine for the x axis title. Axis labels, however, require
more work, and to be honest the solution is far too ugly to be useful
(this is because tableGrob is not vectorised for x and y). I post it
anyway, to justify the time I wasted on this :P

library(gridExtra)

breaks <- 1:4
## labels, to be split in 3 lines
labels <- paste("italic('first line') * alpha[", 1:4, "] * bold('last
line')",sep="")

my.labels <- function ()
{
structure(function(label, x, y) {

gTree(children=
do.call(gList,
mlply(data.frame(x=as.numeric(convertUnit(x, "native", "x")),
y=as.numeric(convertUnit(y, "native",
"y")),label=label),
function(x,y,label)
tableGrob(strsplit(label, "\\*")[[1]], parse=TRUE,


theme=theme.list(gpar.corefill = gpar(fill = NA,
col = NA),

core.just = "center"),
vp=viewport(unit(x,"native"),
y=unit(-2.5,"lines"), just="bottom")))))

}, class = "theme", type = "text", call = match.call())
}

qplot(1:4,1:4, geom="blank") +
scale_x_continuous(breaks=breaks, labels=labels) + xlab("")+
opts(axis.text.x = my.labels(), plot.margin = unit(c(1, 1, 3, 0.5), "lines"))


If I were you, I would look into tikzDevice instead; with some tweaks
of the plot margin, you could get a decent result with LaTeX
interpreting the labels.

Best,

baptiste

Aaron Polhamus

unread,
Jul 26, 2011, 3:48:19 AM7/26/11
to baptiste auguie, ggplot2
Baptiste, 

Thank you so much for patiently weighing in on this one. After hours of fiddling around I've come to see it your way--probably not worth it. I couldn't get your sample code to work, but here is the closest I came to a solution: 


library(ggplot2)

spacing <- 0 #We can adjust how much blank space we have beneath the chart here

labels1= paste('Group',c('A','B','C','D'))
labels2 = rep(paste(rep('\n',spacing),collapse=''),length(labels1))
labels <- paste(labels1,labels2)

qplot(1:4,1:4, geom="blank") +
 scale_x_continuous(breaks=1:length(labels), labels=labels) + xlab("")+
 opts(plot.margin = unit(c(1, 1, 3, 0.5), "lines"),
      axis.text.x = theme_text(face='bold', size=14))

xseq <- seq(0.15,0.9,length.out=length(labels)) #Assume for now that 0.15 and 0.9 are constant plot boundaries

sample_df <- data.frame(group=rep(labels1,each=2),subgroup=rep(c('a','b'),4),pop=sample(1:10,8))
popLabs <- by(sample_df,sample_df$group,function(subData){
  paste(paste(subData$subgroup,' [n = ', subData$pop,']',sep=''),collapse='\n')
})

gridText <- paste("grid.text(label='\n",popLabs,"',x=",xseq,',y=0.1)',sep='')

sapply(gridText, function(x){ #Evaluate parsed character string for each element of gridText
  eval(parse(text=x))
})

grid.gedit("GRID.text", gp=gpar(fontsize=12))

Cheers, 
Aaron 


2011/7/20 baptiste auguie <bapt...@googlemail.com>
Reply all
Reply to author
Forward
0 new messages