R: Extract scale name from ggplot object
I was wondering how to extract the scale name (i.e. the legend name) from an object in the ggplot
most general way. In general, what I mean is that it fetches the same thing no matter how you changed the name of the scale using name
in a function scale
or using labs
.
For example:
library("ggplot2")
set.seed(3489243)
rho <- round(rnorm(25, 0, 5))
profit <- 0.5 + 0.3 * rho + rnorm(25, 0, 1)
BetaAdjusted <- factor(c(rep(TRUE, 15), rep(FALSE, 10)))
returns.both <- data.frame(rho, profit, BetaAdjusted)
p1 <- ggplot(aes(x=rho, y=profit, shape = BetaAdjusted),
data=returns.both) +
geom_point() + scale_shape_discrete(name = "Is Beta Adjusted?")
p2 <- ggplot(aes(x=rho, y=profit, shape = BetaAdjusted),
data=returns.both) +
geom_point() + labs(shape = "Is Beta Adjusted?")
I want to extract text Is Beta Adjusted
from p1
and p2
using the same code. Is it possible? Using labs(p2)
gives me the text below the list of labels, but using labs(p1)
gives me the text in the list of weights. I don't want to look at two places for the same text depending on user input. In the end, p1
it p2
creates the same schedule.
source to share
This solution is heavily dependent on the scale implementation, so use with caution (as ggplot2 may change this at some point).
p <- qplot(vs, wt, shape = factor(gear), color = factor(am), data = mtcars)
guide_names <- function(p, aes = c("shape", "colour", "size")) {
sc <- as.list(p$scales)$scales
nms <- lapply(sc, "[[", "name")
if (length(nms) > 0) names(nms) <- lapply(sc, "[[", "aesthetics")
modifyList(p$labels[names(p$labels) %in% aes], nms)
}
guide_names(p)
# $colour
# [1] "factor(am)"
#
# $shape
# [1] "factor(gear)"
guide_names(p + labs(shape = "A") + labs(color = "B"))
# $colour
# [1] "B"
#
# $shape
# [1] "A"
guide_names(p + scale_shape_discrete(name = "S") + scale_color_discrete(name = "C"))
# $colour
# [1] "C"
#
# $shape
# [1] "S"
# if both are specified, scale_* is prefered
guide_names(p + labs(shape = "A") + scale_shape_discrete(name = "S"))
# $shape
# [1] "S"
#
# $colour
# [1] "factor(am)"
source to share
Is this what you mean?
set.seed(3489243)
rho <- round(rnorm(25, 0, 5))
profit <- 0.5 + 0.3 * rho + rnorm(25, 0, 1)
BetaAdjusted <- factor(c(rep(TRUE, 15), rep(FALSE, 10)))
returns.both <- data.frame(rho, profit, BetaAdjusted)
p1 <- ggplot(aes(x=rho, y=profit, shape = BetaAdjusted),
data=returns.both) +
geom_point() + scale_shape_discrete(name = "Is Beta Adjusted?")
p2 <- ggplot(aes(x=rho, y=profit, shape = BetaAdjusted),
data=returns.both) +
geom_point() + labs(shape = "Is Beta Adjusted?")
lapply(list(p1,p2),function(x)x$labels$shape)
[[1]] [1] "BetaAdjusted"
[[2]] [1] "Beta corrected?"
source to share
It's easier to extract information from p2:
> p2$labels$shape
#[1] "Is Beta Adjusted?"
Whereas in p1 the text is "Beta corrected?" "hidden" in p1 $ scales:
> p1$scales
#Reference class object of class "Scales"
#Field "scales":
#[[1]]
#discrete_scale(aesthetics = "shape", scale_name = "shape_d",
# palette = shape_pal(solid), name = "Is Beta Adjusted?")
Alternatively, if the exact text is "Beta corrected?" not required, you can use the same syntax for both p1 and p2:
> p1$labels$shape
#[1] "BetaAdjusted"
> p2$labels$shape
#[1] "Is Beta Adjusted?"
source to share