如何在数据之上绘制密度曲线以显示 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))
我希望绘制数据分布内的密度曲线。我听说过(不是专家)所谓的对数正态分布? 我的数据如下:
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))