Наложение гистограммы на кривую плотности

#r #ggplot2 #histogram

#r #ggplot2 #гистограмма

Вопрос:

Я пытаюсь составить гистограмму значений плотности и наложить ее на кривую функции плотности (не на оценку плотности).

Используя простой стандартный пример, вот некоторые данные:

 x <- rnorm(1000)
  

Я могу сделать:

 q <- qplot( x, geom="histogram")
q   stat_function( fun = dnorm )
  

но это дает масштаб гистограммы по частотам, а не по плотностям. с ..density.. я могу получить правильный масштаб на гистограмме:

 q <- qplot( x,..density.., geom="histogram")
q
  

Но теперь это выдает ошибку:

 q   stat_function( fun = dnorm )
  

Есть ли что-то, чего я не вижу?

Другой вопрос, есть ли способ построить кривую функции, например curve() , но затем не в виде слоя?

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

1. Проблема в том, что вы определили глобальную y для своего графика, используя ..density.. внутри qplot . Это сбивает с толку stat_function . Самым простым решением было бы написать qplot(x, geom = 'blank') geom_histogram(aes(y = ..density..)) stat_function(fun = dnorm) . Смотрите мой подробный ответ ниже

2. Эквивалентом curve(dnorm, -4, 4) было бы qplot(x = -4:4, stat = 'function', fun = dnorm, geom = 'line')

3. Ах да, я пробовал это с функцией в качестве первого аргумента, но теперь видите, что пошло не так. Спасибо!

Ответ №1:

Вот так!

 # create some data to work with
x = rnorm(1000);

# overlay histogram, empirical density and normal density
p0 = qplot(x, geom = 'blank')     
  geom_line(aes(y = ..density.., colour = 'Empirical'), stat = 'density')    
  stat_function(fun = dnorm, aes(colour = 'Normal'))                         
  geom_histogram(aes(y = ..density..), alpha = 0.4)                          
  scale_colour_manual(name = 'Density', values = c('red', 'blue'))   
  theme(legend.position = c(0.85, 0.85))

print(p0)
  

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

1. P.S. Если вы работаете с реальными данными, обязательно передайте аргументы эмпирического среднего и sd в функцию dnorm, синтаксис см. в справке stat_function.

2. Просто из любопытства: как бы это было сделано с помощью функции ggplot ()? Я едва понял, как работает ggplot (), поэтому я чувствую себя немного странно, используя этот подход для своих материалов.

3. @Jemus42 вы могли бы поменять первую строку на что-то вроде этого «ggplot(data.frame(x), aes(x = x)) »

4. @Jemus42 Почему это? Без передачи mean и sd в args в stat_function я вообще ничего не получаю.

5. Существует проблема с наложением гистограмм и оценок плотности, которая заключается в том, что оценки плотности действительно должны быть сдвинуты на половину ширины ячейки, чтобы получить наиболее точное и эстетически приятное представление. Я так и не смог понять, как это сделать. Есть желающие?

Ответ №2:

Более простая альтернатива ответу Рамната, передающая наблюдаемое среднее значение и стандартное отклонение и использующая ggplot вместо qplot :

 df <- data.frame(x = rnorm(1000, 2, 2))

# overlay histogram and normal density
ggplot(df, aes(x))  
  geom_histogram(aes(y = after_stat(density)))  
  stat_function(
    fun = dnorm, 
    args = list(mean = mean(df$x), sd = sd(df$x)), 
    lwd = 2, 
    col = 'red'
  )
  

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

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

1. Это очень удобный ответ, поскольку он предоставляет способ построения гистограммы и кривой плотности, даже если они принадлежат разным распределениям, если это необходимо (как это было для меня). Спасибо!

2. Исходный вопрос касается подгонки кривой плотности, а не конкретно одного гауссова. Если вы хотите понять, почему это решение не работает, попробуйте установить для данных значение df <- data.frame(x = c(rnorm(1000, 2, 2), rnorm(1000, 12, 2)))

3. @Megatron, Нет, OP запросил «кривую функции плотности (не оценку плотности)» . Так что я все еще думаю, что это правильно. Ваш пример показывает, что функция нормальной плотности в некоторых случаях может не быть хорошим описанием данных, но это не главное.

Ответ №3:

Как насчет использования geom_density() from ggplot2 ? Вот так:

 df <- data.frame(x = rnorm(1000, 2, 2))

ggplot(df, aes(x))  
  geom_histogram(aes(y=..density..))    # scale histogram y
  geom_density(col = "red")
  

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

Это также работает для мультимодальных распределений, например:

 df <- data.frame(x = c(rnorm(1000, 2, 2), rnorm(1000, 12, 2), rnorm(500, -8, 2)))

ggplot(df, aes(x))  
  geom_histogram(aes(y=..density..))    # scale histogram y
  geom_density(col = "red")
  

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

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

1. Потому что OP запросил «кривую функции плотности (не оценку плотности)» . geom_density дает оценку плотности.

2. Возможно, это не то, о чем просил OP, но это помогло с тем, что я искал!

3. @Axeman В чем разница между функцией плотности и оценкой плотности?

Ответ №4:

Я пытаюсь получить набор данных iris. Вы должны быть в состоянии видеть нужный вам график в этом простом коде:

 ker_graph <- ggplot(iris, aes(x = Sepal.Length))   
geom_histogram(aes(y = ..density..),
colour = 1, fill = "white")  
geom_density(lwd = 1.2,
linetype = 2,
colour = 2)