2015-03-04 14 views
5

Sto tracciando dati che hanno sia una categoria e una sottocategoria (vedere i dati esempio qui sotto) e mi piacerebbe per visualizzare questi con loro annidati (questo esempio è stato creato in Excel):Come si tracciano grafici con assi di categorie annidate?

Nested categories from Excel
Il migliore che è venuta in mente in R è quello di creare una nuova colonna con i nomi desiderati, in questo modo:

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() 

questo almeno mantiene entrambi i livelli di categorie, ma duplica tutte le principali etichette di categoria: enter image description here

Qualcuno sa qualcosa di meglio, che assomiglierebbe più all'output di Excel?

risposta

3

penso che l'approccio aspetto va bene:

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)) 

Ma se si vuole qualcosa di più vicino alla excel guardare, un approccio è quello di utilizzare gtable funzioni per estrarre la striscia e inserirla sotto le etichette di segno di spunta, quindi inserire alcune linee di confine tra le categorie principali. Tieni presente che il codice riportato sotto è specifico per i tuoi dati di esempio.

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

Modifica Un tentativo di greggio a generalizzare

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

La seconda versione è esattamente ciò che volevo, grazie. Non ho familiarità con il pacchetto Gtable quindi ho evidentemente bisogno di un po 'di lettura per capire come generalizzare questo per gestire diversi gruppi di categorie! –

+0

Baptiste ha preparato alcune note sulle funzioni di 'gtable', disponibili su [https://github.com/baptiste/gtable/wiki/Description](https://github.com/baptiste/gtable/wiki/Description) –

+0

Vedi la modifica - un tentativo grossolano di generalizzazione. –

3

testato, ma prova:

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

Anche se, la larghezza di ciascuna main.cat sarebbe lo stesso, e l'etichetta della stessa può essere posizionato in alto.

+0

La sfaccettatura tipo di opere, ma si finisce con tutte le suddivisioni che appaiono per ogni sfaccettatura (cioè per la sezione A, hai ancora b1, b2, b3, c1, per la sezione B hai ancora a1, a2, c1; ecc.). C'è un modo per rimuovere le categorie non necessarie? –

+1

Con l'argomento '' scale = 'libero''' a '' facet_grid'' (risposta modificata). – MrGumble

Problemi correlati