Jak zarządzać współrzędnymi t, b, l, R w gtable (), aby poprawnie wykreślić etykiety i znaczniki drugiej osi Y
Używam facet_wrap i był również w stanie wykreślić wtórną Oś Y. Jednak etykiety nie są wykreślane w pobliżu osi, a raczej są wykreślane bardzo daleko. Zdaję sobie sprawę, że wszystko zostanie rozwiązane, jeśli zrozumiem, jak manipulować układem współrzędnych gtable (t, b, l, r) grobów. Czy ktoś mógłby wyjaśnić jak i co faktycznie przedstawiają-t: r = c(4,8,4,4) oznacza co.
Istnieje wiele linków do drugorzędnych yaxis z ggplot, jednak gdy nrow / ncol jest więcej niż 1, zawodzą. Więc proszę nauczyć mnie podstaw geometrii siatki i zarządzania lokalizacją grobs.
Edit: kod
this is the final code written by me :
library(ggplot2)
library(gtable)
library(grid)
library(data.table)
library(scales)
# Data
diamonds$cut <- sample(letters[1:13], nrow(diamonds), replace = TRUE)
dt.diamonds <- as.data.table(diamonds)
d1 <- dt.diamonds[,list(revenue = sum(price),
stones = length(price)),
by=c("clarity", "cut")]
setkey(d1, clarity, cut)
# The facet_wrap plots
p1 <- ggplot(d1, aes(x = clarity, y = revenue, fill = cut)) +
geom_bar(stat = "identity") +
labs(x = "clarity", y = "revenue") +
facet_wrap( ~ cut) +
scale_y_continuous(labels = dollar, expand = c(0, 0)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1),
axis.text.y = element_text(colour = "#4B92DB"),
legend.position = "bottom")
p2 <- ggplot(d1, aes(x = clarity, y = stones, colour = "red")) +
geom_point(size = 4) +
labs(x = "", y = "number of stones") + expand_limits(y = 0) +
scale_y_continuous(labels = comma, expand = c(0, 0)) +
scale_colour_manual(name = '', values = c("red", "green"),
labels = c("Number of Stones"))+
facet_wrap( ~ cut) +
theme(axis.text.y = element_text(colour = "red")) +
theme(panel.background = element_rect(fill = NA),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(fill = NA, colour = "grey50"),
legend.position = "bottom")
# Get the ggplot grobs
xx <- ggplot_build(p1)
g1 <- ggplot_gtable(xx)
yy <- ggplot_build(p2)
g2 <- ggplot_gtable(yy)
nrow = length(unique(xx$panel$layout$ROW))
ncol = length(unique(xx$panel$layout$COL))
npanel = length(xx$panel$layout$PANEL)
pp <- c(subset(g1$layout, grepl("panel", g1$layout$name), se = t:r))
g <- gtable_add_grob(g1, g2$grobs[grepl("panel", g1$layout$name)],
pp$t, pp$l, pp$b, pp$l)
hinvert_title_grob <- function(grob){
widths <- grob$widths
grob$widths[1] <- widths[3]
grob$widths[3] <- widths[1]
grob$vp[[1]]$layout$widths[1] <- widths[3]
grob$vp[[1]]$layout$widths[3] <- widths[1]
grob$children[[1]]$hjust <- 1 - grob$children[[1]]$hjust
grob$children[[1]]$vjust <- 1 - grob$children[[1]]$vjust
grob$children[[1]]$x <- unit(1, "npc") - grob$children[[1]]$x
grob
}
j = 1
k = 0
for(i in 1:npanel){
if ((i %% ncol == 0) || (i == npanel)){
k = k + 1
index <- which(g2$layout$name == "axis_l-1") # Which grob
yaxis <- g2$grobs[[index]] # Extract the grob
ticks <- yaxis$children[[2]]
ticks$widths <- rev(ticks$widths)
ticks$grobs <- rev(ticks$grobs)
ticks$grobs[[1]]$x <- ticks$grobs[[1]]$x - unit(1, "npc")
ticks$grobs[[2]] <- hinvert_title_grob(ticks$grobs[[2]])
yaxis$children[[2]] <- ticks
if (k == 1)#to ensure just once d secondary axisis printed
g <- gtable_add_cols(g,g2$widths[g2$layout[index,]$l],
max(pp$r[j:i]))
g <- gtable_add_grob(g,yaxis,max(pp$t[j:i]),max(pp$r[j:i])+1,
max(pp$b[j:i])
, max(pp$r[j:i]) + 1, clip = "off", name = "2ndaxis")
j = i + 1
}
}
# inserts the label for 2nd y-axis
loc_1st_yaxis_label <- c(subset(g$layout, grepl("ylab", g$layout$name), se
= t:r))
loc_2nd_yaxis_max_r <- c(subset(g$layout, grepl("2ndaxis", g$layout$name),
se = t:r))
zz <- max(loc_2nd_yaxis_max_r$r)+1
loc_1st_yaxis_label$l <- zz
loc_1st_yaxis_label$r <- zz
index <- which(g2$layout$name == "ylab")
ylab <- g2$grobs[[index]] # Extract that grob
ylab <- hinvert_title_grob(ylab)
ylab$children[[1]]$rot <- ylab$children[[1]]$rot + 180
g <- gtable_add_grob(g, ylab, loc_1st_yaxis_label$t, loc_1st_yaxis_label$l
, loc_1st_yaxis_label$b, loc_1st_yaxis_label$r
, clip = "off", name = "2ndylab")
grid.draw(g)
@ Sandy tutaj jest kod i jego wyjście
Jedyny problem polegał na tym, że w ostatnim rzędzie dodatkowe etykiety osi Y znajdują się wewnątrz paneli.Próbowałem to rozwiązać, ale nie byłem w stanie
1 answers
Wystąpiły problemy z poleceniami gtable_add_cols()
i gtable_add_grob()
. Dodałem komentarze poniżej.
Aktualizacja do ggplot2 v2.2.0
library(ggplot2)
library(gtable)
library(grid)
library(data.table)
library(scales)
diamonds$cut <- sample(letters[1:4], nrow(diamonds), replace = TRUE)
dt.diamonds <- as.data.table(diamonds)
d1 <- dt.diamonds[,list(revenue = sum(price),
stones = length(price)),
by=c("clarity", "cut")]
setkey(d1, clarity, cut)
# The facet_wrap plots
p1 <- ggplot(d1, aes(x = clarity, y = revenue, fill = cut)) +
geom_bar(stat = "identity") +
labs(x = "clarity", y = "revenue") +
facet_wrap( ~ cut, nrow = 2) +
scale_y_continuous(labels = dollar, expand = c(0, 0)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1),
axis.text.y = element_text(colour = "#4B92DB"),
legend.position = "bottom")
p2 <- ggplot(d1, aes(x = clarity, y = stones, colour = "red")) +
geom_point(size = 4) +
labs(x = "", y = "number of stones") + expand_limits(y = 0) +
scale_y_continuous(labels = comma, expand = c(0, 0)) +
scale_colour_manual(name = '', values = c("red", "green"),
labels =c("Number of Stones")) +
facet_wrap( ~ cut, nrow = 2) +
theme(axis.text.y = element_text(colour = "red")) +
theme(panel.background = element_rect(fill = NA),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(fill = NA, colour = "grey50"),
legend.position = "bottom")
# Get the ggplot grobs
g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
# Grab the panels from g2 and overlay them onto the panels of g1
pp <- c(subset(g1$layout, grepl("panel", g1$layout$name), select = t:r))
g <- gtable_add_grob(g1, g2$grobs[grepl("panel", g1$layout$name)],
pp$t, pp$l, pp$b, pp$l)
# Function to invert labels
hinvert_title_grob <- function(grob){
widths <- grob$widths
grob$widths[1] <- widths[3]
grob$widths[3] <- widths[1]
grob$vp[[1]]$layout$widths[1] <- widths[3]
grob$vp[[1]]$layout$widths[3] <- widths[1]
grob$children[[1]]$hjust <- 1 - grob$children[[1]]$hjust
grob$children[[1]]$vjust <- 1 - grob$children[[1]]$vjust
grob$children[[1]]$x <- unit(1, "npc") - grob$children[[1]]$x
grob
}
# Get the y label from g2, and invert it
index <- which(g2$layout$name == "ylab-l")
ylab <- g2$grobs[[index]] # Extract that grob
ylab <- hinvert_title_grob(ylab)
# Put the y label into g, to the right of the right-most panel
# Note: Only one column and one y label
g <- gtable_add_cols(g, g2$widths[g2$layout[index, ]$l], pos = max(pp$r))
g <-gtable_add_grob(g,ylab, t = min(pp$t), l = max(pp$r)+1,
b = max(pp$b), r = max(pp$r)+1,
clip = "off", name = "ylab-r")
# Get the y axis from g2, reverse the tick marks and the tick mark labels,
# and invert the tick mark labels
index <- which(g2$layout$name == "axis-l-1-1") # Which grob
yaxis <- g2$grobs[[index]] # Extract the grob
ticks <- yaxis$children[[2]]
ticks$widths <- rev(ticks$widths)
ticks$grobs <- rev(ticks$grobs)
plot_theme <- function(p) {
plyr::defaults(p$theme, theme_get())
}
tml <- plot_theme(p1)$axis.ticks.length # Tick mark length
ticks$grobs[[1]]$x <- ticks$grobs[[1]]$x - unit(1, "npc") + tml
ticks$grobs[[2]] <- hinvert_title_grob(ticks$grobs[[2]])
yaxis$children[[2]] <- ticks
# Put the y axis into g, to the right of the right-most panel
# Note: Only one column, but two y axes - one for each row of the facet_wrap plot
g <- gtable_add_cols(g, g2$widths[g2$layout[index, ]$l], pos = max(pp$r))
nrows = length(unique(pp$t)) # Number of rows
g <- gtable_add_grob(g, rep(list(yaxis), nrows),
t = unique(pp$t), l = max(pp$r)+1,
b = unique(pp$b), r = max(pp$r)+1,
clip = "off", name = paste0("axis-r-", 1:nrows))
# Get the legends
leg1 <- g1$grobs[[which(g1$layout$name == "guide-box")]]
leg2 <- g2$grobs[[which(g2$layout$name == "guide-box")]]
# Combine the legends
g$grobs[[which(g$layout$name == "guide-box")]] <-
gtable:::cbind_gtable(leg1, leg2, "first")
grid.newpage()
grid.draw(g)
Więc nie jest to strona z tutorialami, a to może wywołać gniew innych użytkowników SO, ale jest za dużo na komentarz.
Nie jest to jednak możliwe w przypadku, gdy nie jest to możliwe.]}library(ggplot2)
p <- ggplot(mtcars, aes(x = mpg, y = disp)) + geom_point()
Pobierz ggplot grob.
g <- ggplotGrob(p)
Poznaj fabułę:
1) gtable_show_layout()
podaj schemat układu GTABLE wykresu. Duża przestrzeń w środku jest lokalizacja panelu działki. Kolumny po lewej stronie i pod panelem zawierają osie y i X. I jest margines wokół całej działki. Indeksy określają położenie każdej komórki w tablicy. Zauważ na przykład, że panel znajduje się w trzecim wierszu czwartej kolumny.
gtable_show_layout(g)
2) ramka danych układu. g$layout
zwraca ramkę danych zawierającą nazwy grobów zawartych w rysuj wraz z ich lokalizacjami w tabeli gtable: t, l, b i r (stojąc na górze, lewej, prawej i na dole). Zauważ na przykład, że panel znajduje się w t = 3, l = 4, b=3, r = 4. Jest to ta sama lokalizacja panelu, która została uzyskana powyżej na schemacie.
g$layout
3) schemat układu stara się podać wysokości i szerokości wierszy i kolumn, ale mają tendencję do nakładania się. Zamiast tego użyj g$widths
i g$heights
. 1null width and height to szerokość i wysokość panelu plot. Uwaga że 1null jest 3. wysokość i 4 Szerokość-3 i 4 ponownie.
Teraz narysuj wykres facet_wrap i facet_grid.
p1 <- ggplot(mtcars, aes(x = mpg, y = disp)) + geom_point() +
facet_wrap(~ carb, nrow = 1)
p2 <- ggplot(mtcars, aes(x = mpg, y = disp)) + geom_point() +
facet_grid(. ~ carb)
g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
Obie działki wyglądają tak samo, ale ich GTABLE różnią się. Różnią się również nazwy grobów składowych.
Często wygodnie jest uzyskać podzbiór ramki danych układu zawierający indeksy (T, l, b i r) grobów wspólnego typu; powiedzmy wszystkie panele.
pp1 <- subset(g1$layout, grepl("panel", g1$layout$name), select = t:r)
pp2 <- subset(g2$layout, grepl("panel", g2$layout$name), select = t:r)
Zauważ na przykład, że wszystkie panele są w wierszu 4 (pp1$t
, pp2$t
).pp1$r
odnosi siÄ™ do kolumn zawierajÄ…cych panele wykresu;pp1$r + 1
odnosi siÄ™ do kolumn po prawej stronie paneli;max(pp1$r)
odnosi się do prawej kolumny most, która zawiera panel;max(pp1$r) + 1
odnosi się do kolumny po prawej stronie prawej kolumny most, która zawiera panel;
i tak dalej.
Na koniec narysuj wykres facet_wrap z więcej niż jednym wierszem.
p3 <- ggplot(mtcars, aes(x = mpg, y = disp)) + geom_point() +
facet_wrap(~ carb, nrow = 2)
g3 <- ggplotGrob(p3)
Zbadaj Wykres jak wcześniej, ale także Ustaw ramkę danych układu, aby zawierała indeksy panele.
pp3 <- subset(g3$layout, grepl("panel", g3$layout$name), select = t:r)
Jak można się było spodziewać, pp3
mówi, że panele wykresu znajdują się w trzech kolumnach (4, 7 i 10) i dwóch wierszach (4 i 8).
Indeksy te są używane podczas dodawania wierszy lub kolumn do tabeli gtable oraz podczas dodawania grobów do tabeli GTABLE. Sprawdź te polecenia za pomocą ?gtable_add_rows
i gtable_add_grob
.
Naucz się także niektórych grid
, zwłaszcza jak konstruować groby i jak używać jednostek (niektóre zasoby są podane w znaczniku r-grid
tutaj NA SO.
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-11-16 07:12:32