How to change facet labels?
Solution 1
Change the underlying factor level names with something like:
# Using the Iris data
> i <- iris
> levels(i$Species)
[1] "setosa" "versicolor" "virginica"
> levels(i$Species) <- c("S", "Ve", "Vi")
> ggplot(i, aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .)
Solution 2
Here is a solution that avoids editing your data:
Say your plot is facetted by the group
part of your dataframe, which has levels control, test1, test2
, then create a list named by those values:
hospital_names <- list(
'Hospital#1'="Some Hospital",
'Hospital#2'="Another Hospital",
'Hospital#3'="Hospital Number 3",
'Hospital#4'="The Other Hospital"
)
Then create a 'labeller' function, and push it into your facet_grid call:
hospital_labeller <- function(variable,value){
return(hospital_names[value])
}
ggplot(survey,aes(x=age)) + stat_bin(aes(n=nrow(h3),y=..count../n), binwidth=10)
+ facet_grid(hospital ~ ., labeller=hospital_labeller)
...
This uses the levels of the data frame to index the hospital_names list, returning the list values (the correct names).
Please note that this only works if you only have one faceting variable. If you have two facets, then your labeller function needs to return a different name vector for each facet. You can do this with something like :
plot_labeller <- function(variable,value){
if (variable=='facet1') {
return(facet1_names[value])
} else {
return(facet2_names[value])
}
}
Where facet1_names
and facet2_names
are pre-defined lists of names indexed by the facet index names ('Hostpital#1', etc.).
Edit: The above method fails if you pass a variable/value combination that the labeller doesn't know. You can add a fail-safe for unknown variables like this:
plot_labeller <- function(variable,value){
if (variable=='facet1') {
return(facet1_names[value])
} else if (variable=='facet2') {
return(facet2_names[value])
} else {
return(as.character(value))
}
}
Answer adapted from how to change strip.text labels in ggplot with facet and margin=TRUE
edit: WARNING: if you're using this method to facet by a character column, you may be getting incorrect labels. See this bug report. fixed in recent versions of ggplot2.
Solution 3
Here's another solution that's in the spirit of the one given by @naught101, but simpler and also does not throw a warning on the latest version of ggplot2.
Basically, you first create a named character vector
hospital_names <- c(
`Hospital#1` = "Some Hospital",
`Hospital#2` = "Another Hospital",
`Hospital#3` = "Hospital Number 3",
`Hospital#4` = "The Other Hospital"
)
And then you use it as a labeller, just by modifying the last line of the code given by @naught101 to
... + facet_grid(hospital ~ ., labeller = as_labeller(hospital_names))
Hope this helps.
Solution 4
Here's how I did it with facet_grid(yfacet~xfacet)
using ggplot2, version 2.2.1:
facet_grid(
yfacet~xfacet,
labeller = labeller(
yfacet = c(`0` = "an y label", `1` = "another y label"),
xfacet = c(`10` = "an x label", `20` = "another x label")
)
)
Note that this does not contain a call to as_labeller()
-- something that I struggled with for a while.
This approach is inspired by the last example on the help page Coerce to labeller function.
Solution 5
The EASIEST way to change WITHOUT modifying the underlying data is:
- Create an object using
as_labeller()
. If the column names begin with a number or contain spaces or special characters, don't forget to use back tick marks:
# Necessary to put RH% into the facet labels
hum_names <- as_labeller(
c(`50` = "RH% 50", `60` = "RH% 60",`70` = "RH% 70",
`80` = "RH% 80",`90` = "RH% 90", `100` = "RH% 100"))
- Add to the ggplot:
ggplot(dataframe, aes(x = Temperature.C, y = fit)) +
geom_line() +
facet_wrap(~Humidity.RH., nrow = 2, labeller = hum_names)
Related videos on Youtube
wishihadabettername
Updated on January 30, 2022Comments
-
wishihadabettername over 2 years
I have used the following
ggplot
command:ggplot(survey, aes(x = age)) + stat_bin(aes(n = nrow(h3), y = ..count.. / n), binwidth = 10) + scale_y_continuous(formatter = "percent", breaks = c(0, 0.1, 0.2)) + facet_grid(hospital ~ .) + theme(panel.background = theme_blank())
to produce
I'd like to change the facet labels, however, to something shorter (like
Hosp 1
,Hosp 2
...) because they are too long now and look cramped (increasing the height of the graph is not an option, it would take too much space in the document). I looked at the facet_grid help page but cannot figure out how.-
Samuel Saari almost 3 yearsMost answers are very verbose. I found a simple answer (community.rstudio.com/t/changing-sep-in-labeller/7369/2), and made an example with it. See down below.
-
-
Arnaud A about 10 yearsNice, but will not work with facet_wrap, whereas @Vince solution will work with facet_wrap too.
-
Arnaud A about 10 years@wishihadabettername: To avoid changing underlying data, you can use:
ggplot(transform(iris, Species = c("S", "Ve", "Vi")[as.numeric(Species)]), aes(Petal.Length)) + stat_bin() + facet_grid(Species ~ .)
-
naught101 about 10 years@ArnaudAmzallag: Correct, though if someone feels like donating some time, it could in the future.
-
naught101 over 9 yearsAdded a fail-safe for unknown facetting variables.
-
Andreas over 8 yearsNotice: This does not work in ggplot2 v.2 - the labeller function has changed. @mbirons answer works stackoverflow.com/a/34811062/162832
-
n1k31t4 over 8 yearsWhich verison of ggplot2 is
as_labeller
in? I have found some source code for on the CRAN GitHub repository, but after upgrading to the latest version (on CRAN!) I don't seem to have the function. -
mbiron over 8 yearsThat's weird. I also updated through CRAN. Here is the documentation docs.ggplot2.org/dev/as_labeller.html
-
naught101 almost 8 yearsThis is cool. What happens when you have two variables in your facet grid though? Like
hospital ~ gender
or something? Is there a way to use labellers on both axes? I can't see anything obvious in the docs. -
yanes about 7 yearsthis works!!! I wasn't able to apply the other solutions because some of the suggested solutions were deprecated on current ggplot2 versions.
-
PatrickT over 6 yearsInteresting, but this doesn't always work, whereas editing the factors always does.
-
thomas88wp over 6 yearsNote if you started with naught's answer, this one only works with a c() not a list().
-
Brian D over 6 yearsrelated... if you want the panel label to be a bquote() expression (e.g.,
levels(x$measurements) <- c(bquote(Area ~~ (cm^2)), bquote(Length ~~ (cm)))
) it will not appear in mathematical expression. How would one show expressions as facet labels? -
Brian D over 6 yearsrelated for including expressions in the facet label, use
labeller
option tofacet_grid
: stackoverflow.com/questions/37089052/… -
Jens almost 6 yearssorry, it does not work as it also changes the column content
-
jsta almost 6 yearsYou can construct these named vectors with
setNames()
stackoverflow.com/a/22428439/3362993 -
Calum You over 5 yearsOne great part of this is that this works with both axes of the facet grid!
-
filups21 over 5 yearsIt may be a bit nicer to use:
new_names <- c('setosa' = 'Bristle-pointed iris', 'versicolor' = 'Poison flag iris', 'virginica' = 'Virginia iris')
and then in the mutate you could create a new column thusly:mutate(Spec = new_names[Species])
-
Tung about 5 years
-
Landak about 5 yearsThis I think is the most elegant method -- it is effective and works with ggplot2 version 3.0.0.9000
-
4rj4n over 4 yearsan answer to @naught101 's question would be the answer by domi : stackoverflow.com/a/37778906/8124725 Without this addition, this doesn't work for me, yielding NA's for the variable that I did not include.
-
wolfsatthedoor almost 4 yearsHow to do this if you have two facets though?
-
wolfsatthedoor almost 4 yearsThis gives NAs for all the labels for me :(
-
wolfsatthedoor almost 4 yearsShould the higher order variable be repeated in facet1_names?
-
mbiron almost 4 years@wolfsatthedoor check out @bovender's answer
-
wolfsatthedoor almost 4 years@mbiron yeah but its two X facets not X and Y
-
stragu almost 4 yearsThis is incorrect, as: 1. the different Hosp1, Hosp2... variables do not exist. The original question uses one single column called "hospital" in which the strings are contained 2. even if you had different columns, your command would look for objects called Hospital1, Hospital2, etc. and would throw an error because they don't exist. 3. as @Jens said, if you used strings instead, i.e. "Hospital1", it would fill the whole column with that value. You might be looking for a
mutate()
combined with acase_when()
? Not sure why this was upvoted as it definitely would not work. -
Denis Cousineau over 3 yearsbut it does not work when there are two facets, e.g., type~Humidity
-
ADF over 2 yearsCan we update this since the labeller used here is now deprecated?
-
qdread over 2 years@DenisCousineau in that case use
labeller = labeller(Type = c(...), Humidity = c(...))
where the ... are the key value pairs -
qdread over 2 yearsAlso I'd note that if you are just prefixing everything with
RH%
, a more robust solution would be to replace step 1 in this answer withhum_names <- as_labeller(function(x) paste('RH%', x))