2015-03-04 14 views
5

jestem wykreślania danych, które mają zarówno kategorię i podkategorię (patrz przykładowe dane poniżej) i chciałbym, aby wyświetlić te z nich zagnieżdżony (ten przykład został utworzony w programie Excel):Jak wykreślić wykresy z osiami zagnieżdżonych kategorii?

Nested categories from Excel
najlepszym mam wymyślić w R jest stworzenie nowej kolumny z pożądanych nazwisk, tak:

df <- data.frame(main.cat = c("A", "A", "B", "B", "B", "C"), 
       second.cat = c("a1", "a2", "b1", "b2", "b3", "c1"), 
       value = c(2, 3, 4, 2.5, 1.5, 2.3)) 

df$x.labels <- paste(df$second.cat, df$main.cat, sep = "\n") 

ggplot(data = df, aes(x = x.labels, y = value)) + geom_point() 

to przynajmniej zachowuje oba poziomy kategoriach, ale powiela wszystkich głównych wytwórni kategorii: enter image description here

Czy ktoś wie o czymś lepszym, który będzie bardziej przypominał wydruki Excela?

Odpowiedz

3

Myślę, że podejście facet jest w porządku:

library(ggplot2) 
library(gtable) 
library(grid) 

df <- data.frame(main.cat = c("A", "A", "B", "B", "B", "C"), 
       second.cat = c("a1", "a2", "b1", "b2", "b3", "c1"), 
       value = c(2, 3, 4, 2.5, 1.5, 2.3)) 

p = ggplot(data = df, aes(x = second.cat, y = value)) + 
    geom_point() + facet_grid(.~main.cat, space = "free_x", scales = "free_x") + 
    theme(strip.background = element_rect(fill = NA)) 

Ale jeśli chcesz coś bliżej Excel patrzeć, jedno podejście jest użycie gtable funkcje wyodrębnić pas i włóż go poniżej etykiet fajką, następnie wstaw kilka linii granicznych między głównymi kategoriami. Zauważ, że poniższy kod jest specyficzny dla Twoich przykładowych danych.

p = p + theme(panel.spacing = unit(0, "lines")) 
g = ggplotGrob(p) 
gtable_show_layout(g) # to see the layout 

# Add a row below the x-axis tick mark labels, 
# the same height as the strip 
g = gtable_add_rows(g, g$height[6], 8) 

# Get the strip grob 
stripGrob = gtable_filter(g, "strip") 

# Insert the strip grob into the new row 
g = gtable_add_grob(g, stripGrob, 9, 4, 9, 8) 

# remove the old strip 
g = g[-6, ] 

# Insert line grobs as boundary lines between major categories 
linesGrob = linesGrob(gp = gpar(col = "grey75")) 
for(i in c(5,7)) g = gtable_add_grob(g, linesGrob, t=7, l=i, b=8, r=i) 

# Insert new columns of zero width to take the line grobs for the first and last boundary lines 
for(i in c(3, 9)) { 
    g = gtable_add_cols(g, unit(0, "lines"), i) 
    g = gtable_add_grob(g, linesGrob, t=7, l=i+1, b=8, r=i+1) 
} 

grid.newpage() 
grid.draw(g) 

enter image description here

Edit Surowy próba uogólnienia

library(ggplot2) 
library(gtable) 
library(grid) 

df <- data.frame(main.cat = c("A", "A", "B", "B", "C", "D"), 
       second.cat = c("a1", "a2", "b1", "b2", "c1", "d1"), 
       value = c(2, 3, 4, 2.5, 1.5, 2.3)) 

p = ggplot(data = df, aes(x = second.cat, y = value)) + 
    geom_point() + facet_grid(.~main.cat, space = "free_x", scales = "free_x") + 
    theme(strip.background = element_rect(fill = NA)) 


p = p + theme(panel.spacing = unit(0, "lines")) 
g = ggplotGrob(p) 
gtable_show_layout(g) # to see the layout 

# Get the indices for the panels (t=top, l=left, ... 
panels <- c(subset(g$layout, grepl("panel", g$layout$name), se=t:r)) 

# Get the strip grob 
stripGrob = gtable_filter(g, "strip") 

# Its height is 
height = stripGrob$height 

# Add a row below the x-axis tick mark labels, 
# the same height as the strip. 
g = gtable_add_rows(g, height, unique(panels$b+1)) 

# Insert the strip grob into the new row 
g = gtable_add_grob(g, stripGrob, 
         t = unique(panels$b+2), 
         l = min(panels$l), 
         r = max(panels$r)) 

# Insert line grobs as boundary lines between major categories 
linesGrob = linesGrob(gp = gpar(col = "grey75")) 
panelsR = panels$r[-length(panels$r)] 
for(i in panelsR+1) g = gtable_add_grob(g, linesGrob, 
         t=unique(panels$b+1), 
         l=i, 
         b=unique(panels$b+2)) 

# Insert new columns of zero width to take the line grobs for the first and last boundary lines 
panelBound = c(3, max(panels$r)+1) 
for(i in panelBound) { 
    g = gtable_add_cols(g, unit(0, "lines"), i) 
    g = gtable_add_grob(g, linesGrob, 
        t=unique(panels$b+1), 
        l=i+1, 
        b=unique(panels$b+2)) 
} 

# remove the old strip 
g = g[-6, ] 

# Draw it 
grid.newpage() 
grid.draw(g) 
+0

Druga wersja jest dokładnie tym, czego chciałem, dziękuję. Nie jestem zaznajomiony z pakietem gtable, więc najwyraźniej mam trochę do zrobienia, aby dowiedzieć się, jak to uogólnić, aby obsłużyć różne zestawy kategorii! –

+0

Baptiste przygotowało notatki dotyczące funkcji 'gtable', dostępne pod adresem [https://github.com/baptiste/gtable/wiki/Description](https://github.com/baptiste/gtable/wiki/Description] –

+0

Zobacz edycja - prymitywna próba uogólnienia. –

3

Nietestowane, ale spróbuj:

ggplot(data=df, aes(x=second.cat, y=value)) + geom_point() + facet_grid(~ main.cat, scales = 'free') 

Aczkolwiek, szerokość każdego main.cat byłaby taka sama, a sama etykieta może być umieszczona tylko na górze.

+0

The szlifowaniem rodzaju prac, ale w końcu z wszystkich działów pojawiających się na każdym aspekcie (tj sekcja A, nadal masz b1, b2, b3, c1; dla sekcji B nadal masz a1, a2, c1, itd.). Czy istnieje sposób na usunięcie niepotrzebnych kategorii? –

+1

Z argumentem '' scale = 'free''' na '' facet_grid'' (edytowana odpowiedź). – MrGumble