I would like to propose two ideas re: themes.
First, the addition of an ellipsis parameter ..., which would be used
to overwrite any of the settings of a particular theme. As an example,
theme_bw2 <- function (base_size = 12, base_family = "", ...){
modifyList(theme_bw(base_size = base_size, base_family =
base_family), list(...))
}
(p <-
qplot(mpg, wt, data=mtcars) +
theme_bw2(18, panel.grid.major=theme_line(colour="grey90", linetype=2)) )
I find it more intuitive to have it all wrapped in a single call to
theme_xxx() rather than subsequent changes with opts(...). Further,
defining all themes in this manner with respect to the default theme
(theme_grey()) would signal more clearly which parameters are altered
from one theme to the other.
Second, it could be nice to use some user feedback to fine-tune and
extend the set of pre-defined themes that ship with ggplot2. What
opts() do we use most of the time? What groups of options work well
together and are used by many people? Have people defined themes that
match the templates of powerpoint/beamer presentations? Specific
options for particular journals?
Perhaps a good way to find out is by sharing such ideas. For
convenience I started a new page on the ggplot2 wiki <
https://github.com/hadley/ggplot2/wiki/Themes > with two themes that I
have to source() repeatedly.
_____________________
## minimalistic theme to save ink, and make E. Tufte happy
theme_minimal <- function (base_size = 12, base_family = "")
{
structure(list(axis.line = theme_blank(), axis.text.x =
theme_text(family = base_family,
size = base_size * 0.8, lineheight = 0.9, vjust = 1),
axis.text.y = theme_text(family = base_family, size = base_size *
0.8, lineheight = 0.9, hjust = 1), axis.ticks =
theme_segment(colour = "black",
size = 0.2), axis.title.x = theme_text(family = base_family,
size = base_size, vjust = 1), axis.title.y =
theme_text(family = base_family,
size = base_size, angle = 90, vjust = 0.5),
axis.ticks.length = unit(0.3,
"lines"), axis.ticks.margin = unit(0.5, "lines"),
legend.background = theme_rect(colour = NA), legend.key =
theme_rect(colour = NA),
legend.key.size = unit(1.2, "lines"), legend.key.height = NA,
legend.key.width = NA, legend.text = theme_text(family = base_family,
size = base_size * 0.8), legend.text.align = NA,
legend.title = theme_text(family = base_family, size = base_size *
0.8, face = "bold", hjust = 0), legend.title.align = NA,
legend.position = "right", legend.direction = "vertical",
legend.box = NA, panel.background = theme_rect(fill = "white",
colour = NA), panel.border = theme_rect(fill = NA,
colour = "grey90"), panel.grid.major = theme_line(colour =
"grey90",
size = 0.2), panel.grid.minor = theme_line(colour = "grey98",
size = 0.5), panel.margin = unit(0.25, "lines"),
strip.background = theme_rect(fill = NA, colour = NA),
strip.text.x = theme_text(family = base_family, size = base_size *
0.8), strip.text.y = theme_text(family = base_family,
size = base_size * 0.8, angle = -90), plot.background =
theme_rect(colour = NA),
plot.title = theme_text(family = base_family, size = base_size *
1.2), plot.margin = unit(c(1, 1, 0.5, 0.5), "lines")),
class = "options")
}
p + theme_minimal()
## options to expand the plotting area to the full viewport
opts_fullframe <- function(){
structure(list(legend.position = "none",
panel.background = theme_blank(),
panel.grid.major = theme_blank(),
panel.grid.minor = theme_blank(),
panel.margin = unit(0,"null"),
plot.margin = rep(unit(0,"null"),4),
axis.ticks = theme_blank(),
axis.text.x = theme_blank(),
axis.text.y = theme_blank(),
axis.title.x = theme_blank(),
axis.title.y = theme_blank(),
axis.ticks.length = unit(0,"null"),
axis.ticks.margin = unit(0,"null")), class = "options")
}
p + opts_fullframe()
Looking forward to your comments on either proposal.
Best regards,
baptiste
My contribution is very simple, probably not worth much, but when I make graphs for poster presentations, I iike to add + theme_gray(base_size = 18) so the text stands out enough and tracks well with the text on the poster. It's really easy to forget this, expecially when proofing poster on the screen where you often blow them up to check details.
Bryan
****************
Prof. Bryan Hanson
Dept of Chemistry & Biochemistry
DePauw University
Greencastle IN 46135 USA
> --
> 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
I like this as well. However, one thing that I occasionally bump into
that this would make even worse (or rather, more "surprising") has to do
with theme_text's. Using the base_size argument to a theme is a great
way set the scale of all the text. However, if I also want to make some
other changes to some text (rotating, say), I have to remember to reset
the size in that call (usually looking at the theme_gray() call to see
how the size of it relates to base_size.
For example:
p <- qplot(mpg, wt, data=mtcars)
# Increase the text size and also rotate the y axis title
p + theme_bw(base_size = 18) + opts(axis.title.y=theme_text(angle=0))
# or using theme_bw2 proposed above to
# increase the text size and rotate the y axis title
p + theme_bw2(18, axis.title.y=theme_text(angle=0))
# This resets the text size (and family) to the default from
# theme_text (plain and size 10). You need to do
p + theme_bw2(18, axis.title.y=theme_text(size=18,angle=0))
# This involves specifying the size multiple times and in
# multiple places. Even harder
# Increase the text size and rotate the y axis labels
p + theme_bw2(18, axis.text.y=theme_text(angle=90))
# should really be
p + theme_bw2(18, axis.text.y=theme_text(size=0.8*18, angle=90))
# to keep the size from being changed.
Unfortunately, this would be a hard change, I think. Because then all
themes are iterative updates to each part of the theme separately.
Defaults become not function argument defaults, but the first layer of
inheritance. aes behaves something like this now.
These examples are meant more as a caution. It is already easy to
forget to reset the size, and if it was all in one call, it would be
even easier to forget (since you already specified it in the function call).
> Second, it could be nice to use some user feedback to fine-tune and
> extend the set of pre-defined themes that ship with ggplot2. What
> opts() do we use most of the time? What groups of options work well
> together and are used by many people? Have people defined themes that
> match the templates of powerpoint/beamer presentations? Specific
> options for particular journals?
> Perhaps a good way to find out is by sharing such ideas. For
> convenience I started a new page on the ggplot2 wiki<
> https://github.com/hadley/ggplot2/wiki/Themes> with two themes that I
> have to source() repeatedly.
I pretty much use theme_bw exclusively. But every one in awhile I need
the fullframe one, and have to hunt down each part of it; thanks for
putting it in one place. I can see journal specific ones being useful
(organizational specific themes are probably needed as well, but are
only of interest inside that org.)
--
Brian S. Diggs, PhD
Senior Research Associate, Department of Surgery
Oregon Health & Science University
Interesting, thanks for bringing this up. I wonder what led to the
design decision of mapping size to gpar()$fontsize rather than to
gpar()$cex for this purpose. That would still leave the problem of
base_family, though.
That being said, I'm pretty sure this is only a technical detail that
could be overcome, if the basic concept proved popular.
Cheers,
baptiste
Cheers
d.
Thanks,
baptiste
Claudia
>>>> Oregon Health& Science University
>>>>
>>>> --
>>>> 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
>>>>
>>>
>>> --
>>> 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
>>
>>
>
> --
> 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
--
Claudia Beleites
Spectroscopy/Imaging
Institute of Photonic Technology
Albert-Einstein-Str. 9
07745 Jena
Germany
email: claudia....@ipht-jena.de
phone: +49 3641 206-133
fax: +49 2641 206-399
Second, it could be nice to use some user feedback to fine-tune and
extend the set of pre-defined themes that ship with ggplot2. What
opts() do we use most of the time? What groups of options work well
together and are used by many people? Have people defined themes that
match the templates of powerpoint/beamer presentations? Specific
options for particular journals?
Perhaps a good way to find out is by sharing such ideas. For
convenience I started a new page on the ggplot2 wiki <
https://github.com/hadley/ggplot2/wiki/Themes > with two themes that I
have to source() repeatedly.
That would be good. I did something similar with the labeller wiki page
(https://github.com/hadley/ggplot2/wiki/labeller), but it was harder
than I thought it should have been. Most wikis allow a page which is an
image which can be embedded in a page. I couldn't see how to do that
with the wiki on GitHub. You can link to a file in the repository
(either the project or wiki repository), but not having write
permissions on that I couldn't get the image there. What I ended up
doing was creating a repository of my own which contained the images
which could then be displayed inline. I'm open to better/smoother
suggestions.
For images exploring theme, it may also be worthwhile to somehow
indicated where the edge of the image is. Maybe post-processing it to
add a border (described as a guide so people realize it is not part of
the image). This is probably most useful for the minimal theme.
Probably the easiest way (eventually) would be to make an R script
that could take the plot commands and automatically build the
html/markdown page.
Hadley
--
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/
Effectively a weave/noweb approach that has either HTML or markdown as
its output. But the problem is still where is it (it=original source
document)?
You could put it in the git repository that is the source of the wiki on
GitHub. Then the markdown files can be generated from a cloned version
of the repository. But there is still the problem that write access is
limited back to the main site.
If it is elsewhere, then it is further disconnected from the core sources.
In any scenario, the examples need to be regenerated periodically, at
least with each new release. This isn't as automatic as a vignette is.
That said, any of these is still a step in the right direction compared
to the script generating the figures which is detached from the actual
page they are being shown on (which is what I'm using now).
Best,
baptiste
source("http://ggextra.googlecode.com/svn/trunk/inst/tests/themes.r")
which does the following,
themes.list <- list("theme_grey", "theme_bw", "theme_minimal" , "theme_black" ,
"theme_fullframe")
mdf <- data.frame(x <- seq(0, 10), y=rnorm(x),
f=factor(rep(letters[1:2], each=3, length=length(x))))
p <- qplot(x, y, data=mdf, colour=f, geom=c("line", "point"), facets=f~.)
all.themes <- lapply(themes.list,
function(.t) {gTree(children=gList(ggplotGrob(p +
get(.t)()),
rectGrob()))})
library(gridExtra)
library(imguR)
imguR(width=10, height=10)
do.call(grid.arrange, all.themes)
cat(dev.off())
The result at the following url: http://imgur.com/9ZqFW
It looks like some of the proposed themes are not very good with facets.
Cheers,
baptiste
http://groups.google.com/group/ggplot2/browse_thread/thread/a3df8a0d1ee335fb?tvc=2&q=theme
I'm not sure whether things have evolved on that side since then.
baptiste
I've taken the liberty to wrap your lists of options into function()s,
so that I could generate programmatically a graphic for the page with
all current themes. I wonder if we should simplify the code of the
other themes using the modifyList() approach as well.
Best,
baptiste
An alternative might be to have the R code wrapped in special tags,
and use e.g. the brew package to extract and run the code. I have
often thought there was a case for the creation of a 'wiki' R package
that would facilitate these tasks for github and googlecode wikis,
using perhaps brew/ascii/test_that. You'd store wiki pages with
embedded R code in a directory (possibly even part of an R package);
the wiki package would extract the code, run/test it, include the
results (images, tables, etc.) in the appropriate format, and commit
the changes. That would result in reproducible (and source-able)
wikis, essentially.
All the best,
baptiste
PS: by the way, Hadley, any thoughts re the few questions that came up
in this thread,
- choice of mapping geom_text size to fontsize as opposed to cex?
- using modifyList() to specify the changes to themes?
- should some of these themes/variations be included in ggplot2?
- possibility to specify default geom settings along with a theme?
> Hadley
>
>
> --
> Assistant Professor / Dobelman Family Junior Chair
> Department of Statistics / Rice University
> http://had.co.nz/
>
> I've taken the liberty to wrap your lists of options into function()s,
> so that I could generate programmatically a graphic for the page with
> all current themes.
Thanks.
> I wonder if we should simplify the code of the
> other themes using the modifyList() approach as well.
It seemed to me the easiest way to concentrate on what is changing (and
to show which other theme it is similar to).
Best,
Claudia
cex makes many things much more difficult because you can no longer
figure out (e.g.) how wide the axes viewport needs to be, unless you
know the complete sequence of gTrees/viewports in which it will be
embedded.
> - using modifyList() to specify the changes to themes?
Yes, that's a good idea.
> - should some of these themes/variations be included in ggplot2?
I'd be happy to do that.
> - possibility to specify default geom settings along with a theme?
That's probably another version out (i.e. not until next summer). You
can see some thoughts I had in the layers package -
https://github.com/hadley/layers/blob/master/R/aesthetics-defaults.r.
The layers package is where I've been collecting thoughts about how
the next iteration of layers (geoms, stats and position adjustments)
should work.
I should mention the big challenge with modifying default geom
settings is that they're currently set at the time the geom is
created, where theme settings only come into affect when the plot is
rendered. This means that for themes to affect geoms, I need to make
quite a few changes to the pipeline.
theme_poster <- function(base_size = 24) {
update_geom_defaults("point", aes(size = 3))
update_geom_defaults("line", aes(size = 2))
structure(list(
), class = "options")
}
If anyone sees why the base_size in the function above is ignored, I'd appreciate it.
Thanks, Bryan
Well, base_size doesn't do anything because you don't do anything with
it. If you look at theme_bw, base_size appears in the theme_text's. If
you pass it on to another theme which uses the base_size, then you will
see an effect.
theme_poster <- function(base_size = 24) {
update_geom_defaults("point", aes(size = 3))
update_geom_defaults("line", aes(size = 2))
theme_grey(base_size)
}
Now the update_geom_defaults calls are just being used for their side
effects, and it works because theme_poster is called before the geom
defaults are used (in the rendering stage). But it isn't isolated to
that theme call, so you definitely need a function to restore the
defaults (or be happy with the new defaults after the first theme_poster
call). I'd pull those out into a pair of functions that get wrapped
around your plotting:
set_poster_defaults <- function() {
update_geom_defaults("point", aes(size = 3))
update_geom_defaults("line", aes(size = 2))
}
unset_poster_defaults <- function() {
update_geom_defaults("point", aes(size = 2))
update_geom_defaults("line", aes(size = 0.5))
}
theme_poster <- function(base_size = 24) {
theme_grey(base_size)
}
Then theme_poster doesn't do anything but set the base_size (although by
default, so that is something), so you could just use theme_gray(24)
instead.
Your example (from elsewhere in the thread) then looks like:
df <- data.frame(x = rnorm(10), y = rnorm(10))
p1 <- qplot(x = x, y = y, data = df, geom = c("point", "line"), main =
"Test Plot")
print(p1)
p2 <- p1 + theme_poster()
set_poster_defaults()
print(p2)
unset_poster_defaults()
> Thanks, Bryan
On Tue, Jul 19, 2011 at 1:42 AM, Hadley Wickham <had...@rice.edu> wrote:
>> - choice of mapping geom_text size to fontsize as opposed to cex?
>
> cex makes many things much more difficult because you can no longer
> figure out (e.g.) how wide the axes viewport needs to be, unless you
> know the complete sequence of gTrees/viewports in which it will be
> embedded.
I see; though I would have thought the sizes could be calculated as
rendering time with grobWidth/grobHeight.
>
>> - using modifyList() to specify the changes to themes?
>
> Yes, that's a good idea.
Anyone has a good idea how to overcome the problem that Brian pointed
out? -- namely, base_size and base_family need to be re-specified in
each call to theme_text() because their default values are not
inherited from the theme.
Best,
baptiste
> Anyone has a good idea how to overcome the problem that Brian pointed
> out? -- namely, base_size and base_family need to be re-specified in
> each call to theme_text() because their default values are not
> inherited from the theme.
>
During development of a new guides (see another post), Hadley and I wrote this.
You can find it at:
https://github.com/kohske/ggplot2/commit/002e510d0ad80fd3ee4701678b06a30b0aae949f#R/theme.r
--
Kohske Takahashi <takahash...@gmail.com>
Research Center for Advanced Science and Technology,
The University of Tokyo, Japan.
http://www.fennel.rcast.u-tokyo.ac.jp/profilee_ktakahashi.html
I have had issues that prevented me to install the dev version of
ggplot2, but I'll try to get this to work and also test your legend
package. From the commit log you refer to, I gather that themes will
be used to set individual style parameters, is my interpretation
correct? In any case, we can probably use modifyList() for the wiki
theme proposals for now.
Best,
baptiste
I'm not yet following all discussion so I'm not sure if I understand
correctly what you said.
here is an example:
> tg <- theme_grey(base_size = 18)
> tt <- tg$legend.title
> tt
theme_text(family = base_family, face = "bold", size = base_size *
0.8, hjust = 0)
> tt2 <- update_element(tt, face = "italic")
> tt2
theme_text(family = "", face = "italic", size = 14.4, hjust = 0)
thus, in this example, tt2 has size = 14.4 ( = 18 * 0.8), keeping all
parameters other than face.
but please not that this function (update_element) and, more
generally, the theme system may be changed in the future version.
--
Kohske Takahashi <takahash...@gmail.com>
Research Center for Advanced Science and Technology,
The University of Tokyo, Japan.
http://www.fennel.rcast.u-tokyo.ac.jp/profilee_ktakahashi.html
On Wed, Jul 20, 2011 at 5:47 AM, baptiste auguie
On Thu, Jul 21, 2011 at 8:38 AM, Kohske Takahashi
<takahash...@gmail.com> wrote:
> Hi
>
> I'm not yet following all discussion so I'm not sure if I understand
> correctly what you said.
> here is an example:
>
>> tg <- theme_grey(base_size = 18)
>> tt <- tg$legend.title
>> tt
> theme_text(family = base_family, face = "bold", size = base_size *
> 0.8, hjust = 0)
>> tt2 <- update_element(tt, face = "italic")
>> tt2
> theme_text(family = "", face = "italic", size = 14.4, hjust = 0)
>
> thus, in this example, tt2 has size = 14.4 ( = 18 * 0.8), keeping all
> parameters other than face.
> but please not that this function (update_element) and, more
> generally, the theme system may be changed in the future version.
What I initially suggested in this thread was incorporating the
functionality of update_element() into the themes themselves,
theme_grey(base_size = 18, legend.title = theme_text(face = "italic"))
where theme_text() would use the set base_size. Alternatively, a more
verbose incantation could be used,
theme_grey(base_size = 18, legend.title = update_element(legend.title,
face = "italic"))
Best,
baptiste
I think themes really need a complete re-think, because the mechanism
of extension that I thought would be most used (creating new theme_XXX
elements) is very really used, and it would be much more useful to
have some sort of inheritance so that axis.text.x would inherit
properties from axis, text and x theme components.