将分布拟合到 R 中给定的频率值
Fit distribution to given frequency values in R
我有随时间变化的频率值(x
轴单位),如下图所示。经过一些归一化后,这些值可能被视为某些分布的密度函数的数据点。
Q:假设这些频率点来自威布尔分布T
,我如何将最佳威布尔密度函数拟合到这些点 从而从中推断分布 T
参数?
sample <- c(7787,3056,2359,1759,1819,1189,1077,1080,985,622,648,518,
611,1037,727,489,432,371,1125,69,595,624)
plot(1:length(sample), sample, type = "l")
points(1:length(sample), sample)
更新。
为了防止被误解,我想再补充一点解释。通过说 我有随时间变化的频率值(x
轴单位) 我的意思是我有数据表明我有:
- 价值 1 的 7787 个实现
- 价值2的3056个实现
- 价值 3 的 2359 次实现......等等
实现我的目标(我认为不正确)的某种方式是创建一组这些实现:
# Loop to simulate values
set.values <- c()
for(i in 1:length(sample)){
set.values <<- c(set.values, rep(i, times = sample[i]))
}
hist(set.values)
lines(1:length(sample), sample)
points(1:length(sample), sample)
并在 set.values
上使用 fitdistr
:
f2 <- fitdistr(set.values, 'weibull')
f2
为什么我认为这是不正确的方式以及为什么我在 R
中寻找更好的解决方案?
在上面介绍的分布拟合方法中,假设 set.values
是我从分布 [=14= 中实现的 完整 集]
在我最初的问题中,我知道密度曲线第一部分的点 - 我不知道 它的尾巴,我想 估计尾巴 (以及整个 密度函数 )
假设数据来自 Weibull 分布,您可以像这样获得形状和比例参数的估计值:
sample <- c(7787,3056,2359,1759,1819,1189,1077,1080,985,622,648,518,
611,1037,727,489,432,371,1125,69,595,624)
f<-fitdistr(sample, 'weibull')
f
如果你不确定是否是分布式威布尔,我会推荐使用ks.test。这将测试您的数据是否来自假设分布。鉴于您对数据性质的了解,您可以测试几个选定的分布并查看哪个最有效。
对于您的示例,它看起来像这样:
ks = ks.test(sample, "pweibull", shape=f$estimate[1], scale=f$estimate[2])
ks
p 值不显着,因此您不会拒绝数据来自 Weibull 分布的假设。
更新:Weibull 或指数的直方图看起来与您的数据非常匹配。我认为指数分布更适合您。帕累托分布是另一种选择。
f<-fitdistr(sample, 'weibull')
z<-rweibull(10000, shape= f$estimate[1],scale= f$estimate[2])
hist(z)
f<-fitdistr(sample, 'exponential')
z = rexp(10000, f$estimate[1])
hist(z)
这是一个更好的尝试,就像在它使用 optim
找到约束在一个框中的一组值的最佳值之前(由 lower
和 upper
向量定义 optim
调用)。请注意,除了 Weibull 分布形状参数之外,它还缩放 x 和 y 作为优化的一部分,因此我们有 3 个参数需要优化。
不幸的是,当使用所有点时,它几乎总是在约束框的边缘找到一些东西,这向我表明 Weibull 可能不适合所有数据。问题是两点——它们太大了。您会看到尝试拟合 第一个图 中的所有数据。
如果我放弃前两点而只拟合其余的点,我们会得到更好的拟合。您在 第二个情节 中看到了这一点。我认为这是一个很好的拟合,它在任何情况下都是约束框内部的局部最小值。
library(optimx)
sample <- c(60953,7787,3056,2359,1759,1819,1189,1077,1080,985,622,648,518,
611,1037,727,489,432,371,1125,69,595,624)
t.sample <- 0:22
s.fit <- sample[3:23]
t.fit <- t.sample[3:23]
wx <- function(param) {
res <- param[2]*dweibull(t.fit*param[3],shape=param[1])
return(res)
}
minwx <- function(param){
v <- s.fit-wx(param)
sqrt(sum(v*v))
}
p0 <- c(1,200,1/20)
paramopt <- optim(p0,minwx,gr=NULL,lower=c(0.1,100,0.01),upper=c(1.1,5000,1))
popt <- paramopt$par
popt
rms <- paramopt$value
tit <- sprintf("Weibull - Shape:%.3f xscale:%.1f yscale:%.5f rms:%.1f",popt[1],popt[2],popt[3],rms)
plot(t.sample[2:23], sample[2:23], type = "p",col="darkred")
lines(t.fit, wx(popt),col="blue")
title(main=tit)
您可以直接计算最大似然参数,如here所述。
# Defining the error of the implicit function
k.diff <- function(k, vec){
x2 <- seq(length(vec))
abs(k^-1+weighted.mean(log(x2), w = sample)-weighted.mean(log(x2),
w = x2^k*sample))
}
# Setting the error to "quite zero", fulfilling the equation
k <- optimize(k.diff, vec=sample, interval=c(0.1,5), tol=10^-7)$min
# Calculate lambda, given k
l <- weighted.mean(seq(length(sample))^k, w = sample)
# Plot
plot(density(rep(seq(length(sample)),sample)))
x <- 1:25
lines(x, dweibull(x, shape=k, scale= l))
我有随时间变化的频率值(x
轴单位),如下图所示。经过一些归一化后,这些值可能被视为某些分布的密度函数的数据点。
Q:假设这些频率点来自威布尔分布T
,我如何将最佳威布尔密度函数拟合到这些点 从而从中推断分布 T
参数?
sample <- c(7787,3056,2359,1759,1819,1189,1077,1080,985,622,648,518,
611,1037,727,489,432,371,1125,69,595,624)
plot(1:length(sample), sample, type = "l")
points(1:length(sample), sample)
更新。
为了防止被误解,我想再补充一点解释。通过说 我有随时间变化的频率值(x
轴单位) 我的意思是我有数据表明我有:
- 价值 1 的 7787 个实现
- 价值2的3056个实现
- 价值 3 的 2359 次实现......等等
实现我的目标(我认为不正确)的某种方式是创建一组这些实现:
# Loop to simulate values
set.values <- c()
for(i in 1:length(sample)){
set.values <<- c(set.values, rep(i, times = sample[i]))
}
hist(set.values)
lines(1:length(sample), sample)
points(1:length(sample), sample)
并在 set.values
上使用 fitdistr
:
f2 <- fitdistr(set.values, 'weibull')
f2
为什么我认为这是不正确的方式以及为什么我在 R
中寻找更好的解决方案?
在上面介绍的分布拟合方法中,假设
set.values
是我从分布 [=14= 中实现的 完整 集]在我最初的问题中,我知道密度曲线第一部分的点 - 我不知道 它的尾巴,我想 估计尾巴 (以及整个 密度函数 )
假设数据来自 Weibull 分布,您可以像这样获得形状和比例参数的估计值:
sample <- c(7787,3056,2359,1759,1819,1189,1077,1080,985,622,648,518,
611,1037,727,489,432,371,1125,69,595,624)
f<-fitdistr(sample, 'weibull')
f
如果你不确定是否是分布式威布尔,我会推荐使用ks.test。这将测试您的数据是否来自假设分布。鉴于您对数据性质的了解,您可以测试几个选定的分布并查看哪个最有效。
对于您的示例,它看起来像这样:
ks = ks.test(sample, "pweibull", shape=f$estimate[1], scale=f$estimate[2])
ks
p 值不显着,因此您不会拒绝数据来自 Weibull 分布的假设。
更新:Weibull 或指数的直方图看起来与您的数据非常匹配。我认为指数分布更适合您。帕累托分布是另一种选择。
f<-fitdistr(sample, 'weibull')
z<-rweibull(10000, shape= f$estimate[1],scale= f$estimate[2])
hist(z)
f<-fitdistr(sample, 'exponential')
z = rexp(10000, f$estimate[1])
hist(z)
optim
找到约束在一个框中的一组值的最佳值之前(由 lower
和 upper
向量定义 optim
调用)。请注意,除了 Weibull 分布形状参数之外,它还缩放 x 和 y 作为优化的一部分,因此我们有 3 个参数需要优化。
不幸的是,当使用所有点时,它几乎总是在约束框的边缘找到一些东西,这向我表明 Weibull 可能不适合所有数据。问题是两点——它们太大了。您会看到尝试拟合 第一个图 中的所有数据。
如果我放弃前两点而只拟合其余的点,我们会得到更好的拟合。您在 第二个情节 中看到了这一点。我认为这是一个很好的拟合,它在任何情况下都是约束框内部的局部最小值。
library(optimx)
sample <- c(60953,7787,3056,2359,1759,1819,1189,1077,1080,985,622,648,518,
611,1037,727,489,432,371,1125,69,595,624)
t.sample <- 0:22
s.fit <- sample[3:23]
t.fit <- t.sample[3:23]
wx <- function(param) {
res <- param[2]*dweibull(t.fit*param[3],shape=param[1])
return(res)
}
minwx <- function(param){
v <- s.fit-wx(param)
sqrt(sum(v*v))
}
p0 <- c(1,200,1/20)
paramopt <- optim(p0,minwx,gr=NULL,lower=c(0.1,100,0.01),upper=c(1.1,5000,1))
popt <- paramopt$par
popt
rms <- paramopt$value
tit <- sprintf("Weibull - Shape:%.3f xscale:%.1f yscale:%.5f rms:%.1f",popt[1],popt[2],popt[3],rms)
plot(t.sample[2:23], sample[2:23], type = "p",col="darkred")
lines(t.fit, wx(popt),col="blue")
title(main=tit)
您可以直接计算最大似然参数,如here所述。
# Defining the error of the implicit function
k.diff <- function(k, vec){
x2 <- seq(length(vec))
abs(k^-1+weighted.mean(log(x2), w = sample)-weighted.mean(log(x2),
w = x2^k*sample))
}
# Setting the error to "quite zero", fulfilling the equation
k <- optimize(k.diff, vec=sample, interval=c(0.1,5), tol=10^-7)$min
# Calculate lambda, given k
l <- weighted.mean(seq(length(sample))^k, w = sample)
# Plot
plot(density(rep(seq(length(sample)),sample)))
x <- 1:25
lines(x, dweibull(x, shape=k, scale= l))