Jak nałożyć wykresy gęstości w R?


82

Chciałbym nałożyć 2 wykresy gęstości na tym samym urządzeniu za pomocą R. Jak mogę to zrobić? Przeszukałem sieć, ale nie znalazłem żadnego oczywistego rozwiązania.

Moim pomysłem byłoby odczytanie danych z pliku tekstowego (kolumn), a następnie użycie

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

Albo coś w tym duchu.


Dla ggplot2rodziny jest teraz pakiet, ggridgesktóry może to zrobić.
— Liang Zhang

Odpowiedzi:


96

użyj linesdo drugiego:

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

upewnij się jednak, że granice pierwszego wątku są odpowiednie.


9
+1 Możesz potrzebować czegoś nieco bardziej złożonego, gdy dwie gęstości mają różne zakresy, a druga krzywa nie mieści się w granicach wykresu. Następnie można obliczyć gęstości przed wykreśleniem i obliczyć odpowiednie ylimprzy użyciu obiektów range(dens1$y, dens2$y)gdzie dens1i dens2są zawierające dwa obiekty szacowania gęstości. Użyj tego ylimw wezwaniu do plot().
— Gavin Simpson

2
Prawdopodobnie będziesz chciał rozróżnić te dwie linie. Powinno tu pomóc ustawienie szerokości linii ( lwd), typu linii ( lty) lub koloru linii ( col). W tym momencie możesz również rozważyć dodanie legendy, używająclegend()
— nullglob

@Gavin Jeśli OP czyta z pliku, skonstruowałbym rozbudowaną funkcję, która wczytywałaby dane (sapply, lapply), znajdowała zakresy wszystkich zestawów danych, ustawiała domyślny zakres na maksymalny zakres wszystkich, a następnie rysował (linie ) gęstości.
— Roman Luštrik

50

ggplot2 to kolejny pakiet graficzny, który w całkiem sprytny sposób radzi sobie z takimi problemami, jak problem z zasięgiem, o którym wspomina Gavin. Obsługuje również automatyczne generowanie odpowiednich legend i po prostu ogólnie ma bardziej dopracowany wygląd po wyjęciu z pudełka z mniejszą ręczną manipulacją.

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)

wprowadź opis obrazu tutaj


8
Ramka danych OP musi być najpierw stopiona do długiej postaci:ggplot (melt (MyData), mapping = aes (fill = variable, x = value)) + geom_density (alpha = .5)
— cbeleites niezadowolone z SX

1
Niezła fabuła. Co to jest "dat2" ...? co to jest „topienie” (nie znaleziono polecenia)?
— Erik Aronesty,

@ErikAronesty - myślisz, że jest tak samo dobre jak moje w tym momencie, odpowiedziałem na to dwa lata temu! Spekuluję, że miałem inny obiekt nazwany datw moim środowisku tak go nazwał dat2... symulowane dane, które udostępniam, działają jednak zgodnie z reklamą. melt()polecenie pochodzi z pakietu reshape2. W 2011 r. reshape2Został automatycznie załadowany po ggplot2załadowaniu, ale tak już nie jest, więc musisz to zrobić library(reshape2)osobno.
— Chase

23

Dodanie podstawowej wersji grafiki, która dba o limity osi y, dodaje kolory i działa dla dowolnej liczby kolumn:

Jeśli mamy zestaw danych:

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

Następnie, aby wykreślić gęstości:

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

Co daje:

wprowadź opis obrazu tutaj


Podoba mi się ten przykład, ale jeśli masz kolumny danych zawierające wartości NA, to nie działa. Nie jestem pewien, jak zmodyfikować kod, ale byłoby to przydatne
— daisy

1
@daisy zmień tę linię dens <- apply(myData, 2, density)na dens <- apply(myData, 2, density, na.rm=TRUE)i powinna działać.
— Karolis Koncevičius

12

Aby zapewnić kompletny zestaw, oto wersja odpowiedzi Chase'a przy użyciu 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"))

który tworzy taki wykres: wprowadź opis obrazu tutaj


Bez tworzenia nowych data.frame: densityplot(~rnorm(100)+rnorm(100, 10, 5), plot.points=FALSE, ref=TRUE, auto.key = list(space = "right")). Lub dla danych OP densityplot(~Column1+Column2, data=myData).
— Marek

6

Tak to robię w bazie (tak naprawdę jest to wspomniane w komentarzach pierwszej odpowiedzi, ale pokażę tutaj pełny kod, w tym legendę, ponieważ nie mogę jeszcze komentować ...)

Najpierw musisz uzyskać informacje o maksymalnych wartościach dla osi y z wykresów gęstości. Więc musisz najpierw obliczyć gęstości oddzielnie

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

Następnie wykreśl je zgodnie z pierwszą odpowiedzią i zdefiniuj wartości minimalne i maksymalne dla osi y, którą właśnie otrzymałeś. (Ustawiam wartość min na 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")

Następnie dodaj legendę w prawym górnym rogu

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

3

Wziąłem powyższy przykład kraty i wykonałem fajną funkcję. Prawdopodobnie istnieje lepszy sposób, aby to zrobić, zmieniając kształt za pomocą topienia / odlewania. (Skomentuj lub edytuj, jeśli zauważysz poprawę).

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,...)
}

Przykładowe użycie:

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

Możesz skorzystać z ggjoypakietu. Powiedzmy, że mamy trzy różne betadystrybucje, takie jak:

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)

Możesz uzyskać trzy różne dystrybucje w następujący sposób:

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

wprowadź opis obrazu tutaj


2

Zawsze, gdy występują problemy z niedopasowanymi granicami osi, basenależy użyć odpowiedniego narzędzia graficznego matplot. Kluczem jest wykorzystanie argumentów fromi . To trochę hakerskie, ale dość proste, aby się rzucić:todensity.default

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

Fabuła przedstawiająca wynik wywołania matplot.  Obserwowane są dwie krzywe, jedna czerwona, druga czarna;  czarna krzywa rozciąga się wyżej niż czerwona, podczas gdy czerwona krzywa jest „grubsza”.

Dodaj wodotryski jako pożądane ( matplotakceptuje wszystkie standardowe plot/ parargumenty, na przykład lty, type, col, lwd, ...).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.