Zeichnen Sie mehrere Boxplots in einem Diagramm

77

Ich habe meine Daten als .csvDatei mit 12 Spalten gespeichert. Die Spalten zwei bis 11 (beschriftet F1, F2, ..., F11) sind features. Column oneenthält die labeldieser Funktionen entweder goododer bad.

Ich möchte ein plotten boxplotvon allen diesen 11 Funktionen gegen die label, aber getrennt von goododer bad. Mein bisheriger Code lautet:

qplot(Label, F1, data=testData, geom = "boxplot", fill=Label, 
          binwidth=0.5, main="Test") + xlab("Label") + ylab("Features")

Dies zeigt sich jedoch nur F1gegen die label.

Meine Frage ist: Wie kann man mit einigen F2, F3, ..., F11gegen die labelin einem Diagramm zeigen dodge position? Ich habe die Funktionen so normalisiert, dass sie innerhalb des Bereichs [0 1] im gleichen Maßstab liegen.

Die Testdaten finden Sie hier . Ich habe etwas von Hand gezeichnet, um das Problem zu erklären (siehe unten).

handgezeichnetes Boxplot-Beispiel

Samo Jerom
quelle
1
(+1) Ihr Beitrag hatte alles, aber nicht ganz formatiert. Ich denke, das war die Ablehnung. Bitte lernen Sie die SO-Formatierungsoptionen zu verwenden! Es wird dir sehr helfen. Anstatt einen Link zu CSV zu veröffentlichen, sollten Sie dput(testData)die Ausgabe hier verwenden und einfügen, damit Benutzer direkt auf ihr System kopieren / einfügen können.
Arun
Vielen Dank, Arun. Ich werde versuchen, meinen zukünftigen Beitrag zu formatieren. Ich habe versucht, die Daten einzufügen, aber festgestellt, dass sie so viele Zahlen enthalten. Aber ich sollte ein kleineres Spielzeugproblem schaffen.
Samo Jerom

Antworten:

117

Sie sollten Ihre Daten in einem bestimmten Format erhalten, indem Sie Ihre Daten vor dem Plotten schmelzen (siehe unten, wie geschmolzene Daten aussehen). Ansonsten scheint das, was Sie getan haben, in Ordnung zu sein.

require(reshape2)
df <- read.csv("TestData.csv", header=T)
# melting by "Label". `melt is from the reshape2 package. 
# do ?melt to see what other things it can do (you will surely need it)
df.m <- melt(df, id.var = "Label")
> df.m # pasting some rows of the melted data.frame

#     Label variable      value
# 1    Good       F1 0.64778924
# 2    Good       F1 0.54608791
# 3    Good       F1 0.46134200
# 4    Good       F1 0.79421221
# 5    Good       F1 0.56919951
# 6    Good       F1 0.73568570
# 7    Good       F1 0.65094207
# 8    Good       F1 0.45749702
# 9    Good       F1 0.80861929
# 10   Good       F1 0.67310067
# 11   Good       F1 0.68781739
# 12   Good       F1 0.47009455
# 13   Good       F1 0.95859182
# 14   Good       F1 1.00000000
# 15   Good       F1 0.46908343
# 16    Bad       F1 0.57875528
# 17    Bad       F1 0.28938046
# 18    Bad       F1 0.68511766

require(ggplot2)
ggplot(data = df.m, aes(x=variable, y=value)) + geom_boxplot(aes(fill=Label))

boxplot_ggplot2

Bearbeiten: Mir ist klar, dass Sie möglicherweise Facetten müssen. Hier ist auch eine Implementierung davon:

p <- ggplot(data = df.m, aes(x=variable, y=value)) + 
             geom_boxplot(aes(fill=Label))
p + facet_wrap( ~ variable, scales="free")

ggplot2_faceted

Edit 2: Wie Hinzufügen x-labels, y-labels, title, ändern legend heading, ein hinzufügen jitter?

p <- ggplot(data = df.m, aes(x=variable, y=value)) 
p <- p + geom_boxplot(aes(fill=Label))
p <- p + geom_jitter()
p <- p + facet_wrap( ~ variable, scales="free")
p <- p + xlab("x-axis") + ylab("y-axis") + ggtitle("Title")
p <- p + guides(fill=guide_legend(title="Legend_Title"))
p 

ggplot2_geom_plot

Bearbeiten 3: Wie werden geom_point()Punkte an der Mitte des Boxplots ausgerichtet? Es könnte mit gemacht werden position_dodge. Das sollte funktionieren.

require(ggplot2)
p <- ggplot(data = df.m, aes(x=variable, y=value)) 
p <- p + geom_boxplot(aes(fill = Label))
# if you want color for points replace group with colour=Label
p <- p + geom_point(aes(y=value, group=Label), position = position_dodge(width=0.75))
p <- p + facet_wrap( ~ variable, scales="free")
p <- p + xlab("x-axis") + ylab("y-axis") + ggtitle("Title")
p <- p + guides(fill=guide_legend(title="Legend_Title"))
p 

ggplot2_position_dodge_geom_point

Arun
quelle
Eine andere Frage: Wie kann man das x-Etikett und das y-Etikett mit dieser Methode ändern? Zum Beispiel NICHT 'Wert' und 'Variable' verwenden. Vielen Dank.
Samo Jerom
scale_x_discrete (name = "xxx") + scale_y_continuous (name = "yyy")
Samo Jerom
Ich frage mich, wie ich dem Boxplot "Hinzufügen von Rohdatenpunkten" hinzufügen kann. Ich nehme an, geom_point () oder geom_jitter () zu verwenden; Wie ich jedoch versucht habe, überlagern sich die Punkte und können hier nicht in zwei Gruppen unterteilt werden, dh gut oder schlecht.
Samo Jerom
Vielen Dank für Ihre Hilfe. Nur das letzte Bit, ich möchte die Rohdatenpunkte auf dem Boxplot überlagern. Ich habe sowohl geom_point () als auch geom_jitter () ausprobiert. Wenn ich beispielsweise geom_point () verwende, werden die Datenpunkte aus den Datensätzen "gut" und "schlecht" überlagert und in der Mitte der oben gezeigten orangefarbenen und blauen Felder angezeigt. Ich möchte jedoch, dass die Rohpunkte separat entlang der Mittellinie (Whisker) jeder Box überlagert werden. Es tut mir leid, Sie erneut zu stören, aber bitte helfen Sie mir, dieses Problem zu untersuchen. Nochmals vielen Dank.
Samo Jerom
1
1. Ich habe gerade bemerkt, dass dieser lne p <- p + geom_point (aes (y = Wert, Gruppe = Label), position = position_dodge (width = 0.75)) eine Warnung gab: "ymax nicht definiert: Position mit y anpassen" Gefunden eine Online-Lösung p <- p + geom_point (aes (ymax = max (Wert), group = Label), position = position_dodge (width = 0.75)) Es ist jedoch nicht klar, warum "position_dodge" ymax anstelle von y benötigt. Nur eine Notiz für andere Leute, die sich von Warnungen fernhalten wollen.
Samo Jerom
20

Da Sie kein Plot-Paket erwähnen, schlage ich hier die Verwendung der LatticeVersion vor (ich denke, es gibt mehr ggplot2-Antworten als Gitter-Antworten, zumindest seit ich hier in SO bin).

 ## reshaping the data( similar to the other answer)
 library(reshape2)
 dat.m <- melt(TestData,id.vars='Label')
 library(lattice)
 bwplot(value~Label |variable,    ## see the powerful conditional formula 
        data=dat.m,
        between=list(y=1),
        main="Bad or Good")

Geben Sie hier die Bildbeschreibung ein

Agstudy
quelle
Eine andere Frage: Wie kann man das x-Etikett und das y-Etikett mit dieser Methode ändern?
Samo Jerom
@ SamoJerom Sie fügen zB hinzu : ylab="value", xlab="treatment"zur bwplot-Anweisung
agstudy
@agstudy Ich frage mich, wie ich "Hinzufügen von Rohdatenpunkten" hinzufügen kann, die dem Boxplot überlagert sind. Ich nehme an, geom_point () oder geom_jitter () zu verwenden; Wie ich jedoch versucht habe, überlagern sich die Punkte und können hier nicht in zwei Gruppen unterteilt werden, dh gut oder schlecht.
Samo Jerom
20

Mithilfe von Basisgrafiken können wir die at =Position der Box steuern, kombiniert mit boxwex =der Breite der Boxen. Die 1. boxplotAnweisung erstellt ein leeres Diagramm. Fügen Sie dann die 2 Spuren in den folgenden zwei Anweisungen hinzu.

Beachten Sie, dass wir im Folgenden df[,-1]die 1. Spalte (id) von den zu zeichnenden Werten ausschließen. Bei verschiedenen Datenrahmen kann es erforderlich sein, diese in eine Teilmenge für die Spalten zu ändern, die die Daten enthalten, die Sie zeichnen möchten.

boxplot(df[,-1], boxfill = NA, border = NA) #invisible boxes - only axes and plot area
boxplot(df[df$id=="Good", -1], xaxt = "n", add = TRUE, boxfill="red", 
  boxwex=0.25, at = 1:ncol(df[,-1]) - 0.15) #shift these left by -0.15
boxplot(df[df$id=="Bad", -1], xaxt = "n", add = TRUE, boxfill="blue", 
  boxwex=0.25, at = 1:ncol(df[,-1]) + 0.15) #shift to the right by +0.15

Geben Sie hier die Bildbeschreibung ein

Einige Dummy-Daten:

df <- data.frame(
  id = c(rep("Good",200), rep("Bad", 200)),
  F1 = c(rnorm(200,10,2), rnorm(200,8,1)),
  F2 = c(rnorm(200,7,1),  rnorm(200,6,1)),
  F3 = c(rnorm(200,6,2),  rnorm(200,9,3)),
  F4 = c(rnorm(200,12,3), rnorm(200,8,2)))
dww
quelle
12

ggplot-Version des Gitterplots:

library(reshape2)
library(ggplot2)
df <- read.csv("TestData.csv", header=T)
df.m <- melt(df, id.var = "Label")

ggplot(data = df.m, aes(x=Label, y=value)) + 
         geom_boxplot() + facet_wrap(~variable,ncol = 4)

Handlung: Geben Sie hier die Bildbeschreibung ein

Jonas Tundo
quelle
7

Ich weiß, dass dies eine etwas ältere Frage ist, aber es ist auch eine, die ich hatte, und während die akzeptierten Antworten funktionieren, gibt es eine Möglichkeit, etwas Ähnliches zu tun, ohne zusätzliche Pakete wie ggplot oder gattice zu verwenden. Es ist nicht ganz so schön, dass sich die Boxplots überlappen, anstatt nebeneinander zu zeigen, aber:

boxplot(data1[,1:4])
boxplot(data2[,1:4],add=TRUE,border="red")

Bild von dem, was dies tut.

Dadurch werden zwei Sätze von Boxplots eingefügt, wobei der zweite einen Umriss (keine Füllung) in Rot aufweist und die Ausreißer ebenfalls in Rot. Das Schöne ist, dass es für zwei verschiedene Datenrahmen funktioniert, anstatt zu versuchen, sie neu zu formen. Schneller und schmutziger Weg.

user2103050
quelle
4

In Basis R kann eine Formelschnittstelle mit Interaktionen ( :) verwendet werden, um dies zu erreichen.

df <- read.csv("~/Desktop/TestData.csv")
df <- data.frame(stack(df[,-1]), Label=df$Label) # reshape to long format

boxplot(values ~ Label:ind, data=df, col=c("red", "limegreen"), las=2)

Beispiel

Karolis Koncevičius
quelle
Gibt es eine Möglichkeit, das Boxplot zu facettieren?
Adam Bellaïche