Jak ustawić dwie legendy niezależnie w ggplot
Tytuł całkiem dobrze to zakrywa.
Mam dwie legendy, odnoszące się do rozmiaru i koloru, i chciałbym mieć jedną, powiedzmy, na górze i jedną w grafie.
Czy jest to możliwe, a jeśli tak, to jak
TIA
3 answers
Z mojego zrozumienia, w zasadzie jest bardzo ograniczona kontrola nad legendami w ggplot2
. Oto akapit z Księgi Hadleya (strona 111):
ggplot2 stara się wykorzystać jak najmniejszą liczbę Legend, które dokładnie oddają estetykę użytą w fabule. Robi to poprzez łączenie Legend, jeśli zmienna jest używana z więcej niż jedną estetyką. Rysunek 6.14 pokazuje przykład tego dla punktów geom: jeśli zarówno kolor, jak i kształt są odwzorowane do tej samej zmiennej, to tylko potrzebna jest pojedyncza legenda. Aby legendy mogły zostać połączone, muszą mieć taką samą nazwę (ten sam tytuł legendy). Z tego powodu, jeśli zmienisz nazwę jednej ze scalonych Legend, będziesz musiał zmienić ją dla wszystkich z nich.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-01 07:00:01
Można to zrobić poprzez wyodrębnienie osobnych legend z działek, a następnie ułożenie Legend W odpowiedniej działce. Kod tutaj używa funkcji z pakietu gtable
do ekstrakcji, a następnie funkcji z pakietu gridExtra
do aranżacji. Celem jest posiadanie fabuły, która zawiera legendę koloru i legendę rozmiaru. Najpierw wyodrębnij legendę koloru z fabuły, która zawiera tylko legendę koloru. Po drugie, wyodrębnij legendę rozmiaru z wykresu, który zawiera tylko legendę rozmiaru. Po trzecie, narysuj fabuła, która nie zawiera legendy. Po czwarte, ułóż fabułę i dwie legendy w jedną nową fabułę.
# Some data
df <- data.frame(
x = 1:10,
y = 1:10,
colour = factor(sample(1:3, 10, replace = TRUE)),
size = factor(sample(1:3, 10, replace = TRUE)))
library(ggplot2)
library(gridExtra)
library(gtable)
library(grid)
### Step 1
# Draw a plot with the colour legend
(p1 <- ggplot(data = df, aes(x=x, y=y)) +
geom_point(aes(colour = colour)) +
theme_bw() +
theme(legend.position = "top"))
# Extract the colour legend - leg1
leg1 <- gtable_filter(ggplot_gtable(ggplot_build(p1)), "guide-box")
### Step 2
# Draw a plot with the size legend
(p2 <- ggplot(data = df, aes(x=x, y=y)) +
geom_point(aes(size = size)) +
theme_bw())
# Extract the size legend - leg2
leg2 <- gtable_filter(ggplot_gtable(ggplot_build(p2)), "guide-box")
# Step 3
# Draw a plot with no legends - plot
(plot <- ggplot(data = df, aes(x=x, y=y)) +
geom_point(aes(size = size, colour = colour)) +
theme_bw() +
theme(legend.position = "none"))
### Step 4
# Arrange the three components (plot, leg1, leg2)
# The two legends are positioned outside the plot:
# one at the top and the other to the side.
plotNew <- arrangeGrob(leg1, plot,
heights = unit.c(leg1$height, unit(1, "npc") - leg1$height), ncol = 1)
plotNew <- arrangeGrob(plotNew, leg2,
widths = unit.c(unit(1, "npc") - leg2$width, leg2$width), nrow = 1)
grid.newpage()
grid.draw(plotNew)
# OR, arrange one legend at the top and the other inside the plot.
plotNew <- plot +
annotation_custom(grob = leg2, xmin = 7, xmax = 10, ymin = 0, ymax = 4)
plotNew <- arrangeGrob(leg1, plotNew,
heights = unit.c(leg1$height, unit(1, "npc") - leg1$height), ncol = 1)
grid.newpage()
grid.draw(plotNew)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-02 05:05:21
Oto inne rozwiązanie wykorzystujące Pakiety ggplot2
i cowplot
(=Rozszerzenie ggplot2).
Podejście jest podobne do Sandys one, ponieważ wyjmuje legendę jako osobne obiekty i pozwala na samodzielne umieszczanie. Pierwotnie był przeznaczony dla wielu legend, które należą do dwóch lub więcej działek w siatce działek.
Funkcja g_legend
, która jest używana herby, została zaczerpnięta z odpowiedzi .
Idea jest następująca:
- Utwórz Plot1, Plot2,.., PlotX bez legendy
- Utwórz Plot1, Plot2,..., PlotX with legends
- Wyodrębnij legendy z kroku 2 do oddzielnych obiektów
- Skonfiguruj siatkę legend i uporządkuj legendy w taki sposób, w jaki chcesz]}
- tworzenie siatki łączącej wątki i legendy
Wydaje się to dość skomplikowane i czas / Kod comsuming ale skonfigurować raz, można dostosować i używać go do każdego rodzaju fabuły/dostosowanie legendy.
library(ggplot2) library(cowplot) # set up function g_legend<-function(a.gplot){ tmp <- ggplot_gtable(ggplot_build(a.gplot)) leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") legend <- tmp$grobs[[leg]] return(legend) } # Some data df <- data.frame( Name = factor(rep(c("A", "B", "C"), 12)), Month = factor(rep(1:12, each=3)), Temp = sample(0:40, 12), Precip = sample(50:400, 12)) # create plot1 plot1 <- ggplot(df, aes(Month, Temp, fill = Name)) + geom_point(show.legend = F, aes(group = Name, colour = Name), size = 3, shape = 17) + geom_smooth(method = "loess", se = F, aes(group = Name, colour = Name), show.legend = F, size = 0.5, linetype = "dashed") # create plot2 plot2 <- ggplot(df, aes(Month, Precip, fill = Name)) + geom_bar(stat = "identity", position = "dodge", show.legend = F) + geom_smooth(method = "loess", se = F, aes(group = Name, colour = Name), show.legend = F, size = 1, linetype = "dashed") + scale_fill_grey() # create legend1 legend1 <- ggplot(df, aes(Month, Temp)) + geom_point(show.legend = T, aes(group = Name, colour = Name), size = 3, shape = 17) + geom_smooth(method = "loess", se = F,aes(group = Name, colour = Name), show.legend = T, size = 0.5, linetype = "dashed") + labs(colour = "Station") + theme(legend.text=element_text(size=8), legend.title = element_text(face = "italic", angle = -0, size = 10)) # create legend2 legend2 <- ggplot(df, aes(Month, Precip, fill = Name)) + geom_bar(stat = "identity", position = "dodge", show.legend = T) + scale_fill_grey() + guides(fill = guide_legend(title = "", title.theme = element_text(face = "italic", angle = -0, size = 10))) + theme(legend.text=element_text(size=8)) # extract "legends only" from ggplot object legend1 <- g_legend(legend1) legend2 <- g_legend(legend2) # setup legends grid legend1_grid <- cowplot::plot_grid(legend1, align = "v", nrow = 2) # add second legend to grid, specifying its location legends <- legend1_grid + ggplot2::annotation_custom(grob = legend2, xmin = 0.5, xmax = 0.5, ymin = 0.55, ymax = 0.55) # plot "plots" + "legends" (with legends in between plots) cowplot::plot_grid(plot1, legends, plot2, ncol = 3, rel_widths = c(0.45, 0.1, 0.45))
Przykłady:
Przykład http://i65.tinypic.com/jl1lef.png
Zmiana kolejności ostatniego wywołaniaplot_grid()
przenosi legendy w prawo:
cowplot::plot_grid(plot1, plot2, legends, ncol = 3,
rel_widths = c(0.45, 0.45, 0.1))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:25