Як накласти ділянки щільності в R?


82

Я хотів би накласти графіки 2 щільності на одному пристрої з R. Як я можу це зробити? Я шукав в Інтернеті, але не знайшов явного рішення.

Моєю ідеєю було б прочитати дані з текстового файлу (стовпці), а потім використовувати

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

Або щось у цьому дусі.


ggplot2Зараз для сім'ї існує пакет, який " ggridges" може це зробити.
Лянг Чжан

Відповіді:


96

використовувати linesдля другого:

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

переконайтеся, що межі першого сюжету є придатними.


9
+1 Можливо, вам знадобиться щось дещо складніше, коли дві щільності мають різні діапазони, а друга крива не входить в межі графіку. Потім ви можете обчислити щільності перед побудовою графіку та обчислити відповідне, ylimвикористовуючи range(dens1$y, dens2$y)де dens1і dens2є об'єкти, що містять два об'єкти оцінки щільності. Використовуйте це ylimу дзвінку до plot().
Gavin Simpson,

2
Ви, ймовірно, також захочете розрізнити два рядки. Тут має допомогти встановлення ширини рядка ( lwd), типу рядка ( lty) або кольору рядка ( col). На той момент ви також можете подумати про додавання легенди, використовуючиlegend()
nullglob

@Gavin Якщо OP читає з файлу, я побудував би складну функцію, яка б читала дані (sapply, lapply), знаходила діапазони всіх наборів даних, встановлювала діапазон за замовчуванням на максимальний діапазон усіх, а потім складала графік (рядки ) щільності.
Роман Луштрік,

50

ggplot2 - ще один графічний пакет, який обробляє такі речі, як проблему діапазону, про яку згадує Гавін, досить гладко. Він також обробляє автоматичне генерування відповідних легенд і, як правило, має більш полірований відчуття, на мій погляд, нестандартно, з меншими ручними маніпуляціями.

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)

введіть тут опис зображення


8
Data.frame ОП потрібно спершу розплавити, щоб сформувати:ggplot (melt (MyData), mapping = aes (fill = variable, x = value)) + geom_density (alpha = .5)
cbeleites незадоволений SX

1
Гарний сюжет. Що таке "dat2" ...? що таке "плавлення" (команду не знайдено)?
Ерік Аронесті

@ErikAronesty - ти здогадуєшся настільки ж хороший, як і я на даний момент, я відповів на це два роки тому! Я припускаю, що datв моєму середовищі був інший об'єкт, названий так, іменований ним dat2... змодельовані дані, які я надаю, працюють як рекламоване. melt()команда приходить з пакету reshape2. Ще в 2011 році reshape2автоматично завантажувався під час ggplot2завантаження, але це вже не так, тому вам потрібно робити library(reshape2)окремо.
Чейз

23

Додано базову графічну версію, яка піклується про обмеження по осі y, додає кольори та працює для будь-якої кількості стовпців:

Якщо ми маємо набір даних:

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

Тоді для побудови графіку щільності:

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

Що дає:

введіть тут опис зображення


Мені подобається цей приклад, але якщо у вас є стовпці даних, що включають значення NA, він не працює. Я не знаю, як модифікувати код, але це було б корисно
Дейзі

1
@daisy змініть цей рядок dens <- apply(myData, 2, density)на, dens <- apply(myData, 2, density, na.rm=TRUE)і він повинен працювати.
Karolis Koncevičius

12

Щоб надати повний набір, ось версія відповіді Чейза з використанням 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"))

який створює такий сюжет: введіть тут опис зображення


Без створення нового data.frame: densityplot(~rnorm(100)+rnorm(100, 10, 5), plot.points=FALSE, ref=TRUE, auto.key = list(space = "right")). Або для даних OP densityplot(~Column1+Column2, data=myData).
Марек

6

Ось як я це роблю в базі (це фактично згадується в коментарях до першої відповіді, але я покажу тут повний код, включаючи легенду, оскільки я поки що не можу коментувати ...)

Спочатку потрібно отримати інформацію про максимальні значення осі y з графіків щільності. Тож спочатку потрібно фактично розрахувати щільності

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

Потім побудуйте їх відповідно до першої відповіді та визначте мінімальне та максимальне значення для осі y, яку ви щойно отримали. (Я встановив мінімальне значення 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")

Потім додайте легенду у верхній правий кут

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

3

Я взяв наведений вище приклад решітки і зробив чудову функцію. Ймовірно, є кращий спосіб зробити це за допомогою переформування за допомогою розплавлення / лиття. (Коментуйте або редагуйте, якщо помітите покращення.)

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

Приклад використання:

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

Ви можете використовувати ggjoyпакет. Скажімо, у нас є три різні betaдистрибутиви, такі як:

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)

Ви можете отримати три різні дистрибутиви таким чином:

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

введіть тут опис зображення


2

Всякий раз, коли виникають проблеми з невідповідними межами осей, слід використовувати правильний інструмент у baseграфіці matplot. Ключовим є використання аргументів fromта toаргументів density.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))

Сюжет, що відображає результат виклику matplot.  Спостерігаються дві криві, одна червона, інша чорна;  чорна крива поширюється вище червоної, тоді як червона крива є «жирнішою».

Додати прибамбаси за бажанням ( matplotприймає всі стандартні plot/ parаргументи, наприклад lty, type, col, lwd, ...).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.