En ce moment, la légende par défaut ressemble à ceci:ggplot2: Changer la mise en page de la légende
Legend Title
x-1
y-2
z-3
Mais est-il possible de le faire ressembler à quelque chose comme ça?
Legend Title
x-1 y-2 z-3
En ce moment, la légende par défaut ressemble à ceci:ggplot2: Changer la mise en page de la légende
Legend Title
x-1
y-2
z-3
Mais est-il possible de le faire ressembler à quelque chose comme ça?
Legend Title
x-1 y-2 z-3
et voici un hack. il peut y avoir des bugs, cependant:
build_legend <- function(name, mapping, layers, default_mapping, theme) {
legend_data <- plyr::llply(layers, build_legend_data, mapping, default_mapping)
# determine if the elements are aligned horizontally or vertically
horiz<-(!is.null(theme$legend.align) && theme$legend.align=="horizontal")
# Calculate sizes for keys - mainly for v. large points and lines
size_mat <- do.call("cbind", plyr::llply(legend_data, "[[", "size"))
if (is.null(size_mat)) {
key_sizes <- rep(0, nrow(mapping))
} else {
key_sizes <- apply(size_mat, 1, max)
}
title <- theme_render(
theme, "legend.title",
name, x = 0, y = 0.5
)
# Compute heights and widths of legend table
nkeys <- nrow(mapping)
hgap <- vgap <- unit(0.3, "lines")
numeric_labels <- all(sapply(mapping$.label, is.language)) || suppressWarnings(all(!is.na(sapply(mapping$.label, "as.numeric"))))
hpos <- numeric_labels * 1
labels <- lapply(mapping$.label, function(label) {
theme_render(theme, "legend.text", label, hjust = hpos, x = hpos, y = 0.5)
})
# align horizontally
if(!horiz){
label_width <- do.call("max", lapply(labels, grobWidth))
label_width <- convertWidth(label_width, "cm")
label_heights <- do.call("unit.c", lapply(labels, grobHeight))
label_heights <- convertHeight(label_heights, "cm")
width <- max(unlist(plyr::llply(legend_data, "[[", "size")), 0)
key_width <- max(theme$legend.key.size, unit(width, "mm"))
widths <- unit.c(
hgap, key_width,
hgap, label_width,
max(
unit(1, "grobwidth", title) - key_width - label_width,
hgap
)
)
widths <- convertWidth(widths, "cm")
heights <- unit.c(
vgap,
unit(1, "grobheight", title),
vgap,
unit.pmax(
theme$legend.key.size,
label_heights,
unit(key_sizes, "mm")
),
vgap
)
heights <- convertHeight(heights, "cm")
}else{
label_width <- do.call("unit.c", lapply(labels, grobWidth))
label_width <- convertWidth(label_width, "cm")
label_heights <- do.call("max", lapply(labels, grobHeight))
label_heights <- convertHeight(label_heights, "cm")
height <- max(unlist(plyr::llply(legend_data, "[[", "size")), 0)
key_heights <- max(theme$legend.key.size, unit(height, "mm"))
key_width <- unit.pmax(theme$legend.key.size, unit(key_sizes, "mm"))
# width of (key gap label gap) x nkeys
kglg_width<-do.call("unit.c",lapply(1:length(key_width), function(i)unit.c(key_width[i], hgap, label_width[i], hgap)))
widths <- unit.c(
hgap,
kglg_width,
max(
unit(0,"lines"),
unit.c(unit(1, "grobwidth", title) - (sum(kglg_width) - hgap))
)
)
widths <- convertWidth(widths, "cm")
heights <- unit.c(
vgap,
unit(1, "grobheight", title),
vgap,
max(
theme$legend.key.size,
label_heights,
key_heights
),
vgap
)
heights <- convertHeight(heights, "cm")
}
# Layout the legend table
legend.layout <- grid.layout(
length(heights), length(widths),
widths = widths, heights = heights,
just = c("left", "centre")
)
fg <- ggname("legend", frameGrob(layout = legend.layout))
fg <- placeGrob(fg, theme_render(theme, "legend.background"))
fg <- placeGrob(fg, title, col = 2:(length(widths)-1), row = 2)
for (i in 1:nkeys) {
if(!horiz){
fg <- placeGrob(fg, theme_render(theme, "legend.key"), col = 2, row = i+3)
}else{
fg <- placeGrob(fg, theme_render(theme, "legend.key"), col = 1+(i*4)-3, row = 4)
}
for(j in seq_along(layers)) {
if (!is.null(legend_data[[j]])) {
legend_geom <- Geom$find(layers[[j]]$geom$guide_geom())
key <- legend_geom$draw_legend(legend_data[[j]][i, ],
c(layers[[j]]$geom_params, layers[[j]]$stat_params))
if(!horiz){
fg <- placeGrob(fg, ggname("key", key), col = 2, row = i+3)
}else{
fg <- placeGrob(fg, ggname("key", key), col = 1+(i*4)-3, row = 4)
}
}
}
label <- theme_render(
theme, "legend.text",
mapping$.label[[i]], hjust = hpos,
x = hpos, y = 0.5
)
if(!horiz){
fg <- placeGrob(fg, label, col = 4, row = i+3)
}else{
fg <- placeGrob(fg, label, col = 1+(i*4)-1, row = 4)
}
}
fg
}
assignInNamespace("build_legend", build_legend, "ggplot2")
# test and usage
# specify by opts(legend.align="horizontal")
p1<-qplot(mpg, wt, data=mtcars, colour=cyl)+opts(legend.align="horizontal",legend.position="bottom")
p2<-qplot(mpg, wt, data=mtcars, colour=cyl)
Cela fonctionne exactement comme je le souhaiterais. Je vous remercie! –
vous, monsieur, êtes un gentleman et un érudit. Merci pour ça. – fabians
Grande difficulté - vous connaissez évidemment votre chemin autour de ggplot2! Très généreux de partager votre expertise avec le reste d'entre nous. – Aaron
Il y a quelque chose comme guide_legends_box avec une option "horizontal", mais je n'arrive pas à le faire fonctionner.
> d <- qplot(carat, price, data=dsamp, colour=clarity) +
+ scale_color_hue("clarity") +
+ guide_legends_box("clarity",horizontal=T)
donne:
Erreur dans les échelles de legend_desc $: opérateur $ est valide pour des vecteurs atomiques
Peut-être que vous savez ce qui se passe mal ici. Personnellement je pense qu'une partie de la fonctionnalité mentionnée dans la documentation n'est pas encore implémentée.
En regardant la fonction qui crée la légende. Il semble que forcer l'horizontal soit faux. –
Avez-vous déjà demandé aux développeurs de ggplot2? En effet, la valeur par défaut est false, mais le problème est l'objet scalaire dans l'objet plot, qui est vide (essayez d $ scales, il ne donne pratiquement rien). –
De nos jours, vous pouvez simplement utiliser legend.direction = "horizontal". Par exemple:
qplot(carat, price, data=diamonds, colour=color) + opts(legend.position="top", legend.direction="horizontal")
Probablement en raison du travail de développement de Koshke sur les derniers patchs de ggplot2! :) Merci d'avoir signalé cela, et un grand merci à M. Takahashi pour l'avoir lancé dans ggplot! –
Correction, Dr Takahashi. –
Le dernier ggplot2
, opts
a été dépréciée en faveur de theme()
:
qplot(carat, price, data=diamonds, colour=color) +
theme(legend.position="top", legend.direction="horizontal")
l'horizontale dans guide_legends_box() détermine l'alignement de plusieurs boîtes de légende, et non pas celle des éléments de la boîte. try + opts (legend.position = "top") avec plusieurs cases de légende, par exemple, qplot (mpg, wt, données = mtcars, couleur = cyl, taille = facteur (am)) + opts (legend.position = "top"). – kohske
et si vous souhaitez aligner horizontalement l'élément à l'intérieur des boîtes de légende, vous devez probablement réécrire build_legend() par vous-même. – kohske