2017-09-06 3 views
3

Ich möchte die Verteilungen von zwei Variablen mit Box-Plots beschreiben, die sowohl die x- als auch die y-Achse umfassen.Doppel-Box-Plots in ggplot2

Die Seite linked here hat einige nette Beispiele (unten) und es hat Paket mit Basis-Plot - boxplotdbl.

Ich frage mich, ob eine ähnliche Handlung in ggplot2 möglich war. Wie kann ich das Boxplot von Sepal.Length und Sepal.Width mithilfe der folgenden Abbildung und den iris Daten plotten und mit Species färben?

enter image description here

Ich war überrascht zu sehen, dass Code folgenden nahe ist, aber würde die Whisker mag, anstatt das Feld entlang der x-Achse erweitert werden.

library(ggplot2) 
ggplot(iris) + 
    geom_boxplot(aes(x = Sepal.Length, y = Sepal.Width, fill = Species), alpha = 0.3) + 
    theme_bw() 

enter image description here

+1

Dank für diesen Hinweis. Ich habe die Frage bearbeitet, um sie für 'ggplot' spezifischer zu machen. –

+0

Kein Problem, ich würde auch den Link zu CRAN für zukünftige Leser hinzufügen. Warum nicht Basisplot verwenden? – zx8754

+1

Sie könnten Bag-Plots (2d Box-Plots) verwenden, die ich auch besser finde. Lesen Sie diese Antwort https://stackoverflow.com/questions/29501282/plot-multiple-series-of-data-into-a-single-bagplot-with-r –

Antwort

1

Sie können die entsprechenden Nummern von jedem boxplot, erforderlich berechnen & der 2-dimensionalen Boxplots konstruieren verschiedene GEOMS verwenden.

Schritt 1. Plot jeder boxplot der Dimension getrennt:

plot.x <- ggplot(iris) + geom_boxplot(aes(Species, Sepal.Length)) 
plot.y <- ggplot(iris) + geom_boxplot(aes(Species, Sepal.Width)) 

grid.arrange(plot.x, plot.y, ncol=2) # visual verification of the boxplots 

side by side boxplots

Schritt 2. Erhalten, um die berechneten Werte boxplot (einschließlich Ausreißer) in 1-Datenrahmen:

plot.x <- layer_data(plot.x)[,1:6] 
plot.y <- layer_data(plot.y)[,1:6] 
colnames(plot.x) <- paste0("x.", gsub("y", "", colnames(plot.x))) 
colnames(plot.y) <- paste0("y.", gsub("y", "", colnames(plot.y))) 
df <- cbind(plot.x, plot.y); rm(plot.x, plot.y) 
df$category <- sort(unique(iris$Species)) 

> df 
    x.min x.lower x.middle x.upper x.max x.outliers y.min y.lower 
1 4.3 4.800  5.0  5.2 5.8    2.9 3.200 
2 4.9 5.600  5.9  6.3 7.0    2.0 2.525 
3 5.6 6.225  6.5  6.9 7.9  4.9 2.5 2.800 
    y.middle y.upper y.max y.outliers category 
1  3.4 3.675 4.2  4.4, 2.3  setosa 
2  2.8 3.000 3.4    versicolor 
3  3.0 3.175 3.6 3.8, 2.2, 3.8 virginica 

Schritt 3. Erstellen einer separaten Datenrahmen für Ausreißer:

df.outliers <- df %>% 
    select(category, x.middle, x.outliers, y.middle, y.outliers) %>% 
    data.table::data.table() 
df.outliers <- df.outliers[, list(x.outliers = unlist(x.outliers), y.outliers = unlist(y.outliers)), 
          by = list(category, x.middle, y.middle)] 

> df.outliers 
    category x.middle y.middle x.outliers y.outliers 
1: setosa  5.0  3.4   NA  4.4 
2: setosa  5.0  3.4   NA  2.3 
3: virginica  6.5  3.0  4.9  3.8 
4: virginica  6.5  3.0  4.9  2.2 
5: virginica  6.5  3.0  4.9  3.8 

Schritt 4. Dass sie alle zusammen in einem Grundstück:

ggplot(df, aes(fill = category, color = category)) + 

    # 2D box defined by the Q1 & Q3 values in each dimension, with outline 
    geom_rect(aes(xmin = x.lower, xmax = x.upper, ymin = y.lower, ymax = y.upper), alpha = 0.3) + 
    geom_rect(aes(xmin = x.lower, xmax = x.upper, ymin = y.lower, ymax = y.upper), 
      color = "black", fill = NA) + 

    # whiskers for x-axis dimension with ends 
    geom_segment(aes(x = x.min, y = y.middle, xend = x.max, yend = y.middle)) + #whiskers 
    geom_segment(aes(x = x.min, y = y.lower, xend = x.min, yend = y.upper)) + #lower end 
    geom_segment(aes(x = x.max, y = y.lower, xend = x.max, yend = y.upper)) + #upper end 

    # whiskers for y-axis dimension with ends 
    geom_segment(aes(x = x.middle, y = y.min, xend = x.middle, yend = y.max)) + #whiskers 
    geom_segment(aes(x = x.lower, y = y.min, xend = x.upper, yend = y.min)) + #lower end 
    geom_segment(aes(x = x.lower, y = y.max, xend = x.upper, yend = y.max)) + #upper end 

    # outliers 
    geom_point(data = df.outliers, aes(x = x.outliers, y = y.middle), size = 3, shape = 1) + # x-direction 
    geom_point(data = df.outliers, aes(x = x.middle, y = y.outliers), size = 3, shape = 1) + # y-direction 

    xlab("Sepal.Length") + ylab("Sepal.Width") + 
    coord_cartesian(xlim = c(4, 8), ylim = c(2, 4.5)) + 
    theme_classic() 

2D boxplot

Wir visuell überprüfen können, dass die 2D-Boxplots angemessen sind, indem sie mit einem Streudiagramm des ursprünglichen Datensatzes auf den gleichen zwei Dimensionen zu vergleichen:

# p refers to 2D boxplot from previous step 
p + geom_point(data = iris, 
       aes(x = Sepal.Length, y = Sepal.Width, group = Species, color = Species), 
       inherit.aes = F, alpha = 0.5) 

2D boxplot with scatterplot overlay