Na działkach z wieloma zmiennymi aspektu, ggplot2 powtarza etykietę aspektu dla zmiennej "zewnętrznej", zamiast pojedynczego pasma aspektu na wszystkich poziomach "wewnętrznego" zmienna. Mam kod, którego używam do pokrycia powtarzających się zewnętrznych etykiet fasetowych za pomocą pojedynczego pasma krawędziowego przy użyciu gtable_add_grob
z pakietu gtable
.Poszukiwanie rozwiązania dla kodu gtable_add_grob zepsuty przez ggplot 2.2.0
Niestety, ten kod nie działa już z ggplot2 2.2.0 ze względu na zmiany w strukturze grobów pasków aspektu. W szczególności we wcześniejszych wersjach ggplot2 każdy wiersz etykiet aspektów ma własny zestaw grobs. Jednak w wersji 2.2.0 wygląda na to, że każdy pionowy stos etykiet aspektów jest pojedynczym grobem. To łamie mój kod i nie jestem pewien, jak to naprawić.
Oto konkretny przykład, zaczerpnięte z an SO question I answered a few months ago:
# Data
df = structure(list(location = structure(c(1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L), .Label = c("SF", "SS"), class = "factor"), species = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("AGR", "LKA"), class = "factor"),
position = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L,
2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L,
1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L,
2L), .Label = c("top", "bottom"), class = "factor"), density = c(0.41,
0.41, 0.43, 0.33, 0.35, 0.43, 0.34, 0.46, 0.32, 0.32, 0.4,
0.4, 0.45, 0.34, 0.39, 0.39, 0.31, 0.38, 0.48, 0.3, 0.42,
0.34, 0.35, 0.4, 0.38, 0.42, 0.36, 0.34, 0.46, 0.38, 0.36,
0.39, 0.38, 0.39, 0.39, 0.39, 0.36, 0.39, 0.51, 0.38)), .Names = c("location",
"species", "position", "density"), row.names = c(NA, -40L), class = "data.frame")
# Begin with a regular ggplot with three facet levels
p=ggplot(df, aes("", density)) +
geom_boxplot(width=0.7, position=position_dodge(0.7)) +
theme_bw() +
facet_grid(. ~ species + location + position) +
theme(panel.margin=unit(0,"lines"),
strip.background=element_rect(color="grey30", fill="grey90"),
panel.border=element_rect(color="grey90"),
axis.ticks.x=element_blank()) +
labs(x="")
Zaczynamy działce, która ma trzy poziomy aspektach.
Teraz omówimy dwa górne listwy fazowane z paskami Spanning tak, że nie mamy powtarzające się etykiety taśmach:
pg = ggplotGrob(p)
# Add spanning strip labels for species
pos = c(4,11)
for (i in 1:2) {
pg <- gtable_add_grob(pg,
list(rectGrob(gp=gpar(col="grey50", fill="grey90")),
textGrob(unique(densityAGRLKA$species)[i],
gp=gpar(cex=0.8))), t=3,l=pos[i],b=3,r=pos[i]+7,
name=c("a","b"))
}
# Add spanning strip labels for location
pos=c(4,7,11,15)
for (i in 1:4) {
pg = gtable_add_grob(pg,
list(rectGrob(gp = gpar(col="grey50", fill="grey90")),
textGrob(rep(unique(densityAGRLKA$location),2)[i],
gp=gpar(cex=0.8))), t=4,l=pos[i],b=4,r=pos[i]+3,
name = c("c","d"))
}
grid.draw(pg)
To właśnie ta działka wygląda z ggplot2 2.1 0,0:
jednak gdy próbuję tego samego kodu z ggplot2 2.2.0, mam oryginalną fabułę z powrotem, z brak zmian na etykietach pasków. Spojrzenie na strukturę grobu oryginalnej działki p
sugeruje, dlaczego tak się dzieje. Wkleiłem w tabelach grob na końcu tego pytania. Aby zaoszczędzić miejsce, umieściłem tylko wiersze związane z pasmami aspektu.
Patrząc na kolumnę cells
, należy zauważyć, że w wersji 2.1.0 wykresu pierwsze dwie liczby w każdym wierszu są równe 3, 4 lub 5, wskazując pionową pozycję groba względem innych grobs w fabuła. W powyższym kodzie argumenty t
i l
dla są ustawione na wartości 3 lub 4, ponieważ są to rzędy listew krawędziowych, które chciałem pokryć pasmami rozpiętymi.
Teraz spójrz na kolumnę cells
w wersji 2.2.0 wykresu: Pamiętaj, że pierwsze dwie cyfry to zawsze 6. Zwróć uwagę, że paski aspektu składają się tylko z 8 grołów zamiast 24 w wersji 2.1.0 . W wersji 2.2.0 wydaje się, że każdy stos trzech etykiet aspektów jest teraz pojedynczym grobem zamiast trzema oddzielnymi grobami. Więc nawet jeśli zmienię argumenty t
i b
w gtable_add_grob
na 6, wszystkie trzy paski aspektu zostaną pokryte. Oto przykład:
pg = ggplotGrob(p)
# Add spanning strip labels for species
pos = c(4,11)
for (i in 1:2) {
pg <- gtable_add_grob(pg,
list(rectGrob(gp=gpar(col="grey50", fill="grey90")),
textGrob(unique(densityAGRLKA$species)[i],
gp=gpar(cex=0.8))), t=6,l=pos[i],b=6,r=pos[i]+7,
name=c("a","b"))
}
Tak, po tym bardzo rozwlekły wstępie, oto moje pytanie: W jaki sposób można utworzyć obejmujących listwy fazowane z ggplot2 wersji 2.2.0, które wyglądają jak te, które stworzyłem używając gtable_add_grob
z ggplot2 w wersji 2.1.0? Mam nadzieję, że jest prosta korekta, ale jeśli wymaga to poważnej operacji, to też jest w porządku.
ggplot 2.1.0
pg
TableGrob (9 x 19) "layout": 45 grobs z cells name grob 2 1 (3- 3, 4- 4) strip-top absoluteGrob[strip.absoluteGrob.147] 3 2 (4- 4, 4- 4) strip-top absoluteGrob[strip.absoluteGrob.195] 4 3 (5- 5, 4- 4) strip-top absoluteGrob[strip.absoluteGrob.243] 5 4 (3- 3, 6- 6) strip-top absoluteGrob[strip.absoluteGrob.153] 6 5 (4- 4, 6- 6) strip-top absoluteGrob[strip.absoluteGrob.201] 7 6 (5- 5, 6- 6) strip-top absoluteGrob[strip.absoluteGrob.249] 8 7 (3- 3, 8- 8) strip-top absoluteGrob[strip.absoluteGrob.159] 9 8 (4- 4, 8- 8) strip-top absoluteGrob[strip.absoluteGrob.207] 10 9 (5- 5, 8- 8) strip-top absoluteGrob[strip.absoluteGrob.255] 11 10 (3- 3,10-10) strip-top absoluteGrob[strip.absoluteGrob.165] 12 11 (4- 4,10-10) strip-top absoluteGrob[strip.absoluteGrob.213] 13 12 (5- 5,10-10) strip-top absoluteGrob[strip.absoluteGrob.261] 14 13 (3- 3,12-12) strip-top absoluteGrob[strip.absoluteGrob.171] 15 14 (4- 4,12-12) strip-top absoluteGrob[strip.absoluteGrob.219] 16 15 (5- 5,12-12) strip-top absoluteGrob[strip.absoluteGrob.267] 17 16 (3- 3,14-14) strip-top absoluteGrob[strip.absoluteGrob.177] 18 17 (4- 4,14-14) strip-top absoluteGrob[strip.absoluteGrob.225] 19 18 (5- 5,14-14) strip-top absoluteGrob[strip.absoluteGrob.273] 20 19 (3- 3,16-16) strip-top absoluteGrob[strip.absoluteGrob.183] 21 20 (4- 4,16-16) strip-top absoluteGrob[strip.absoluteGrob.231] 22 21 (5- 5,16-16) strip-top absoluteGrob[strip.absoluteGrob.279] 23 22 (3- 3,18-18) strip-top absoluteGrob[strip.absoluteGrob.189] 24 23 (4- 4,18-18) strip-top absoluteGrob[strip.absoluteGrob.237] 25 24 (5- 5,18-18) strip-top absoluteGrob[strip.absoluteGrob.285]
ggplot2 2.2.0
pg
TableGrob (11 x 21) "layout": 42 grobs z cells name grob 28 2 (6- 6, 4- 4) strip-t-1 gtable[strip] 29 2 (6- 6, 6- 6) strip-t-2 gtable[strip] 30 2 (6- 6, 8- 8) strip-t-3 gtable[strip] 31 2 (6- 6,10-10) strip-t-4 gtable[strip] 32 2 (6- 6,12-12) strip-t-5 gtable[strip] 33 2 (6- 6,14-14) strip-t-6 gtable[strip] 34 2 (6- 6,16-16) strip-t-7 gtable[strip] 35 2 (6- 6,18-18) strip-t-8 gtable[strip]
FWIW gtable_add_grob jest wektoryzowane (od początku twierdził, że powinien on być nazywany gtable_add_grob ** s **, chcielibyśmy widzieć mniej pętli) – baptiste
Dzięki Sandy. Pytanie, aby się upewnić, że rozumiem to: Wydaje się, że główną lekcją (przynajmniej dla mnie) jest to, że potrzebujesz 'heights = strip [[1]] $ heights', aby uzyskać wysokość każdego paska w stosie (w w tym przypadku) trzy paski fasetowe. W ten sposób uzyskasz odpowiedni rozmiar w pionie, gdy nakładasz nowe gramy. Czy to jest poprawne? – eipi10
Czy istnieje sposób, aby zautomatyzować to przez programowe ustalanie długości rozpiętości dla każdego rzędu pasków aspektu? Na przykład w tym przypadku górny wiersz ma dwie różne wartości: "AGR" i "LKA", a każda z nich obejmuje cztery aspekty. Środkowy rząd ma dwa zestawy dwóch wartości i każda wartość obejmuje dwa aspekty itd. Czy istnieje sposób na pobranie tej informacji z karty i przekształcenie jej w funkcję automatyzującą proces tworzenia nowych grobs? – eipi10