如何在数据之上绘制密度曲线以显示 R 中的分布

How do you plot density curves on top of the data to show distribution in R

我希望绘制数据分布内的密度曲线。我听说过(不是专家)所谓的对数正态分布? 我的数据如下:

data<- data.frame(
      Day=c(1,2,3,4,5,6,7,8,9,10),
      Variable=c(3,5,20,10,8,18,23,21,16,12))

ggplot(data)  + 
  geom_bar(aes(y=Variable, x=Day),stat="identity", colour="black")+
  labs(title= "",x="",y=expression('Variable'))+  theme_classic()

并且想要这样的东西:

我认为您对条形图和直方图有点混淆。您有一个 条形图 ,在您的情况下,它显示了 y 轴上的一个变量相对于 x 轴上的时间的变化。

直方图看起来像条形图,但它显示了单个变量在整个范围内的分布。这具有 x 轴上的变量值,以及在 y 轴上找到该变量的频率。在直方图上绘制密度曲线是有意义的,但在时间序列上则不然。如果您正在寻找与显示的图相似的视觉效果,您可以获得的最好结果可能是绘制一条移动平均线和条形图,也许是这样的:

ggplot(data, aes(Day, Variable))  + 
  geom_col(colour = "black") +
  geom_smooth(se = FALSE, color = "black") +
  labs(title = "", x = "", y = expression('Variable')) +  
  theme_classic()

我在这里假设您的数据是频率,因此为了 简化后续操作,首先将它们转化为单个观察值的向量。

library(ggplot2)
library(tidyr)
library(dplyr)


long <- with(data, rep(Day, times = Variable))

long[1:20]

[1] 1 1 1 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3

现在使用 ggplot 您可以绘制直方图和密度估计值:

data.frame(Day = long) |>
  ggplot() +
  geom_bar(aes(x = Day), stat = "count") +
  geom_density(aes(x = Day, after_stat(count)))

要拟合两个高斯分布的混合(如参考示例中所示),您可以使用 mclust。请注意,这仅作为示例显示,可能不是处理数据的最佳方式。这里参数G指定模型数量:

library(mclust)
fit <- densityMclust(long, G = 2)

接下来,准备数据以使用 ggplot 分几个步骤进行绘图:

  • 使用 predict
  • x 的合适范围内为两个高斯模型生成密度估计
  • 密度值被缩放以匹配预测在任一模型中的观测值的比例
  • 数据框在 x
  • 上重新排列
x <- seq(0, max(long) + 1, by = 0.1)

dens <- predict(fit, x, what = "cdens") |>
  apply(1, function(z) z*table(fit$classification)) |>
  t() |>
  data.frame() |>
  cbind(x = x) |>
  pivot_longer(cols = c(X1, X2),
               names_to = "K",
               values_to = "y")

最后,通过在 geom_line 中指定数据源是 dens:

,将密度分层到条形图上
data.frame(Day = long) |>
  ggplot() +
  geom_bar(aes(x = Day), stat = "count") +
  geom_line(data = dens,
            aes(x = x, y = y, color = K))