Как заставить график плотности корректно отображать область вблизи пределов?

#r #ggplot2 #kernel-density

#r #ggplot2 #ядро-плотность

Вопрос:

Когда я строю плотности с помощью ggplot, кажется, что границы очень неправильные. Я вижу, что geom_density и другие функции позволяют указывать различные ядра плотности, но ни одна из них, похоже, не устраняет проблему.

Как правильно отображать плотности вокруг границ с помощью ggplot?


В качестве примера давайте построим распределение Хи-квадрат с 2 степенями свободы. Используя встроенные плотности вероятности:

 library(ggplot2)

u = seq(0, 2, by=0.01)
v = dchisq(u, df=2)

df = data.frame(x=u, p=v)

p = ggplot(df)  
    geom_line(aes(x=x, y=p), size=1)  
    theme_classic()  
    coord_cartesian(xlim=c(0, 2), ylim=c(0, 0.5))

show(p)
  

Мы получаем ожидаемый график:

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

Теперь давайте попробуем смоделировать это и построить эмпирическое распределение:

 library(ggplot2)

u = rchisq(10000, df=2)

df = data.frame(x=u)

p = ggplot(df)  
    geom_density(aes(x=x))  
    theme_classic()  
    coord_cartesian(xlim=c(0, 2))

show(p)
  

Мы получаем неверный график:

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

Мы можем попытаться визуализировать фактическое распределение:

 library(ggplot2, dplyr, tidyr)

u = rchisq(10000, df=2)

df = data.frame(x=u)

p = ggplot(df)  
    geom_point(aes(x=x, y=0.5), position=position_jitter(height=0.2), shape='.', alpha=1)  
    theme_classic()  
    coord_cartesian(xlim=c(0, 2), ylim=c(0, 1))

show(p)
  

И это, кажется, выглядит правильно, в отличие от графика плотности:

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

Похоже, проблема связана с ядрами, и geom_density позволяет использовать разные ядра. Но на самом деле они не решают проблему предела. Например, приведенный выше код с triangular выглядит примерно так же:

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

Вот представление о том, что я ожидаю увидеть (конечно, мне нужна плотность, а не гистограмма):

 library(ggplot2)

u = rchisq(10000, df=2)

df = data.frame(x=u)

p = ggplot(df)  
    geom_histogram(aes(x=x), center=0.1, binwidth=0.2, fill='white', color='black')  
    theme_classic()  
    coord_cartesian(xlim=c(0, 2))

show(p)
  

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

Комментарии:

1. Я немного смущен вашим использованием geom_violin — обычно он используется там, где вы использовали бы boxplot, например, показывающий распределение по нескольким дискретным категориям. Когда я запускаю код, я также получаю то, что выглядит иначе, чем изображение, которое вы опубликовали.

2. @Marius Я просто по ошибке вставил неправильный код, чувак. Нет необходимости в лекции по статистике.

Ответ №1:

Обычные методы плотности ядра сталкиваются с проблемами, когда существует ограничение, такое как в этом случае для плотности с поддержкой только выше нуля. Обычной рекомендацией для решения этой проблемы было использование пакета logspline:

 install.packages("logspline")
library(logspline)
png(); fit <- logspline(rchisq(10000, 3))       
plot(fit) ; dev.off()
  

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

Если это необходимо было сделать в среде ggplot2, существует функция dlogspline:

 densdf <- data.frame( y=dlogspline(seq(0,12,length=1000), fit), 
                      x=seq(0,12,length=1000))

ggplot(densdf, aes(y=y,x=x)) geom_line()
  

Возможно, вы настаивали на графике с 2 степенями свободы?

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

Комментарии:

1. Это выглядит еще менее точным, чем график плотности в моем вопросе.

2. Я построил распределение с тремя степенями свободы. Вы построили единицу с 2.