Wie überlagere ich Dichtediagramme in R?


81

Ich möchte 2 Dichtediagramme auf demselben Gerät mit R überlagern. Wie kann ich das tun? Ich habe im Internet gesucht, aber keine offensichtliche Lösung gefunden.

Meine Idee wäre, Daten aus einer Textdatei (Spalten) zu lesen und dann zu verwenden

plot(density(MyData$Column1))
plot(density(MyData$Column2), add=T)

Oder etwas in diesem Sinne.

Antworten:


92

Verwenden Sie linesfür die zweite:

plot(density(MyData$Column1))
lines(density(MyData$Column2))

Stellen Sie jedoch sicher, dass die Grenzen des ersten Diagramms geeignet sind.


9
+1 Möglicherweise benötigen Sie etwas Komplexeres, wenn die beiden Dichten unterschiedliche Bereiche haben und die zweite Kurve nicht in die Plotgrenzen passt. Anschließend können Sie die Dichten vor dem Plotten berechnen und ylimanhand der range(dens1$y, dens2$y)wo dens1und dens2sind die Objekte, die die beiden Dichteschätzungsobjekte enthalten , eine geeignete Dichte berechnen . Verwenden Sie dies ylimim Aufruf an plot().
Gavin Simpson

2
Sie werden wahrscheinlich auch zwischen den beiden Zeilen unterscheiden wollen. Hier sollten Sie die Linienbreite ( lwd), den Linientyp ( lty) oder die Linienfarbe ( col) einstellen. An diesem Punkt können Sie auch eine Legende hinzufügen, indem Sielegend()
nullglob

@Gavin Wenn das OP aus einer Datei liest, würde ich eine ausgefeilte Funktion erstellen, die Daten einliest (sapply, lapply), Bereiche aller Datensätze findet, den Standardbereich auf den maximalen Bereich aller setzt und dann plottet (Linien) ) die Dichten.
Roman Luštrik

50

ggplot2 ist ein weiteres Grafikpaket, das Dinge wie das von Gavin erwähnte Bereichsproblem auf ziemlich raffinierte Weise behandelt. Es handhabt auch das automatische Generieren geeigneter Legenden und hat meiner Meinung nach im Allgemeinen ein ausgefeilteres Gefühl mit weniger manueller Manipulation.

library(ggplot2)

#Sample data
dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
                   , lines = rep(c("a", "b"), each = 100))
#Plot.
ggplot(dat, aes(x = dens, fill = lines)) + geom_density(alpha = 0.5)

Geben Sie hier die Bildbeschreibung ein


8
Der data.frame des OP muss zuerst zu einer langen Form geschmolzen werden:ggplot (melt (MyData), mapping = aes (fill = variable, x = value)) + geom_density (alpha = .5)
cbeleites unzufrieden mit SX

1
Schöne Handlung. Was ist "dat2" ...? Was ist "schmelzen" (Befehl nicht gefunden)?
Erik Aronesty

@ErikAronesty - du denkst, es ist zu diesem Zeitpunkt so gut wie meins, das habe ich vor zwei Jahren beantwortet! Ich spekuliere, dass ich ein anderes Objekt datin meiner Umgebung hatte, das so heißt dat2... die simulierten Daten, die ich zur Verfügung stelle, funktionieren jedoch wie angekündigt. Der melt()Befehl kommt aus dem Paket reshape2. Im Jahr 2011 reshape2wurde automatisch geladen, als ggplot2geladen wurde, aber das ist nicht mehr der Fall, so dass Sie library(reshape2)separat tun müssen .
Chase

21

Hinzufügen einer Basisgrafikversion, die die Grenzen der y-Achse berücksichtigt, Farben hinzufügt und für eine beliebige Anzahl von Spalten funktioniert:

Wenn wir einen Datensatz haben:

myData <- data.frame(std.nromal=rnorm(1000, m=0, sd=1),
                     wide.normal=rnorm(1000, m=0, sd=2),
                     exponent=rexp(1000, rate=1),
                     uniform=runif(1000, min=-3, max=3)
                     )

Dann, um die Dichten zu zeichnen:

dens <- apply(myData, 2, density)

plot(NA, xlim=range(sapply(dens, "[", "x")), ylim=range(sapply(dens, "[", "y")))
mapply(lines, dens, col=1:length(dens))

legend("topright", legend=names(dens), fill=1:length(dens))

Welches gibt:

Geben Sie hier die Bildbeschreibung ein


Ich mag dieses Beispiel, aber wenn Sie Datenspalten haben, die NA-Werte enthalten, funktioniert es nicht. Ich bin nicht sicher, wie ich den Code ändern soll, aber das wäre nützlich
Gänseblümchen

1
@daisy ändere diese Zeile dens <- apply(myData, 2, density)in dens <- apply(myData, 2, density, na.rm=TRUE)und es sollte funktionieren.
Karolis Koncevičius

12

Um einen vollständigen Satz bereitzustellen, hier eine Version von Chases Antwort mit lattice:

dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
                   , lines = rep(c("a", "b"), each = 100))

densityplot(~dens,data=dat,groups = lines,
            plot.points = FALSE, ref = TRUE, 
            auto.key = list(space = "right"))

was eine Handlung wie diese erzeugt: Geben Sie hier die Bildbeschreibung ein


Ohne neue zu erstellen data.frame: densityplot(~rnorm(100)+rnorm(100, 10, 5), plot.points=FALSE, ref=TRUE, auto.key = list(space = "right")). Oder für OP-Daten densityplot(~Column1+Column2, data=myData).
Marek

6

So mache ich es in der Basis (es wird tatsächlich in den Kommentaren der ersten Antwort erwähnt, aber ich werde hier den vollständigen Code anzeigen, einschließlich der Legende, da ich noch keinen Kommentar abgeben kann ...)

Zuerst müssen Sie die Informationen zu den Maximalwerten für die y-Achse aus den Dichtediagrammen abrufen. Sie müssen also zuerst die Dichten separat berechnen

dta_A <- density(VarA, na.rm = TRUE)
dta_B <- density(VarB, na.rm = TRUE)

Zeichnen Sie sie dann gemäß der ersten Antwort und definieren Sie die Min- und Max-Werte für die gerade erhaltene y-Achse. (Ich setze den Min-Wert auf 0)

plot(dta_A, col = "blue", main = "2 densities on one plot"), 
     ylim = c(0, max(dta_A$y,dta_B$y)))  
lines(dta_B, col = "red")

Fügen Sie dann oben rechts eine Legende hinzu

legend("topright", c("VarA","VarB"), lty = c(1,1), col = c("blue","red"))

3

Ich nahm das obige Gitterbeispiel und machte eine raffinierte Funktion. Es gibt wahrscheinlich einen besseren Weg, dies durch Umformen über Schmelzen / Gießen zu tun. (Kommentieren oder bearbeiten Sie, wenn Sie eine Verbesserung sehen.)

multi.density.plot=function(data,main=paste(names(data),collapse = ' vs '),...){
  ##combines multiple density plots together when given a list
  df=data.frame();
  for(n in names(data)){
    idf=data.frame(x=data[[n]],label=rep(n,length(data[[n]])))
    df=rbind(df,idf)
  }
  densityplot(~x,data=df,groups = label,plot.points = F, ref = T, auto.key = list(space = "right"),main=main,...)
}

Anwendungsbeispiel:

multi.density.plot(list(BN1=bn1$V1,BN2=bn2$V1),main='BN1 vs BN2')

multi.density.plot(list(BN1=bn1$V1,BN2=bn2$V1))

2

Sie können das ggjoyPaket verwenden. Nehmen wir an, wir haben drei verschiedene betaVerteilungen wie:

set.seed(5)
b1<-data.frame(Variant= "Variant 1", Values = rbeta(1000, 101, 1001))
b2<-data.frame(Variant= "Variant 2", Values = rbeta(1000, 111, 1011))
b3<-data.frame(Variant= "Variant 3", Values = rbeta(1000, 11, 101))


df<-rbind(b1,b2,b3)

Sie können die drei verschiedenen Verteilungen wie folgt erhalten:

library(tidyverse)
library(ggjoy)


ggplot(df, aes(x=Values, y=Variant))+
    geom_joy(scale = 2, alpha=0.5) +
    scale_y_discrete(expand=c(0.01, 0)) +
    scale_x_continuous(expand=c(0.01, 0)) +
    theme_joy()

Geben Sie hier die Bildbeschreibung ein


2

Immer wenn es Probleme mit nicht übereinstimmenden Achsengrenzen gibt, ist das richtige Werkzeug in baseGrafiken zu verwenden matplot. Der Schlüssel ist, die fromund toArgumente zu nutzen density.default. Es ist ein bisschen hackisch, aber ziemlich einfach, sich selbst zu rollen:

set.seed(102349)
x1 = rnorm(1000, mean = 5, sd = 3)
x2 = rnorm(5000, mean = 2, sd = 8)

xrng = range(x1, x2)

#force the x values at which density is
#  evaluated to be the same between 'density'
#  calls by specifying 'from' and 'to'
#  (and possibly 'n', if you'd like)
kde1 = density(x1, from = xrng[1L], to = xrng[2L])
kde2 = density(x2, from = xrng[1L], to = xrng[2L])

matplot(kde1$x, cbind(kde1$y, kde2$y))

Ein Diagramm, das die Ausgabe des Aufrufs von matplot darstellt.  Es werden zwei Kurven beobachtet, eine rote und eine schwarze;  Die schwarze Kurve erstreckt sich höher als die rote, während die rote Kurve die "dickere" ist.

In Schnickschnack wie gewünscht ( matplotakzeptiert alle Standard plot/ parArgumente, zum Beispiel lty, type, col, lwd, ...).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.