Python 生成对数正态样本,该样本与从中生成的数据相匹配

Python 生成对数正态样本,该样本与从中生成的数据相匹配,python,matplotlib,scipy,distribution,Python,Matplotlib,Scipy,Distribution,我试图根据其他一些样本创建一个新样本,但我做了/理解了一些错误的事情。我有34个样本,我假设它们是相对对数范数分布的。基于这些样本,我想生成2000个新样本。以下是我正在运行的代码: import numpy as np from scipy import stats import matplotlib.pyplot as plt samples = [480, 900, 1140, 1260, 1260, 1440, 1800, 1860, 1980, 2220, 2640, 2700,

我试图根据其他一些样本创建一个新样本,但我做了/理解了一些错误的事情。我有34个样本,我假设它们是相对对数范数分布的。基于这些样本,我想生成2000个新样本。以下是我正在运行的代码:

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

samples = [480, 900, 1140, 1260, 1260, 1440, 1800, 1860, 1980, 2220, 2640, 2700,
           2880, 3420, 3480, 3600, 3840, 4020, 4200, 4320, 4380, 4920, 5160,
           5280, 6900, 7680, 9000, 10320, 10500, 10800, 15000, 21600, 25200,
           39000]
plt.plot(samples, 1 - np.linspace(0, 1, len(samples)))
std, loc, scale = stats.lognorm.fit(samples)
new_samples = stats.lognorm(std, loc=loc, scale=scale).rvs(size=2000)

a = plt.hist(new_samples, bins=range(100, 40000, 200),
             weights=np.ones(len(new_samples)) / len(new_samples))
plt.show()
这是图,正如您所看到的,1000以上的样本确实很少,尽管样本中包含了很多1000以上的样本


如何最好地生成一个更好地表示期望值的样本?

stats.lognorm.fit在这里似乎出了问题

通过拟合样本日志的
stats.norm
,然后使用
exp(mu)
作为刻度,可以提到一种替代方法。这似乎效果好多了

将numpy导入为np
从scipy导入统计信息
将matplotlib.pyplot作为plt导入
样本=[48090011401260126014401800186019802026402700,
2880, 3420, 3480, 3600, 3840, 4020, 4200, 4320, 4380, 4920, 5160,
5280, 6900, 7680, 9000, 10320, 10500, 10800, 15000, 21600, 25200,
39000]
样本=np.数组(样本)
标准、位置、刻度=统计、对数标准、拟合(样本)#2.865850745357322479.9999879223596、1.140062282414484
奇怪的样本=统计数据。对数标准(标准,loc=loc,scale=scale)。rvs(尺寸=2000)
mu,std=stats.norm.fit(np.log(样本))#8.304837454505837,0.972025399925554
刻度=np.exp(μ)#4043.3848507251523
loc=0
新样本=stats.lognorm(标准,loc=loc,scale=scale).rvs(尺寸=2000)
plt.plot(samples,1-np.linspace(0,1,len(samples)),label='give samples')
plt.plot(np.sort(怪异样本),1-np.linspace(0,1,len(怪异样本)),label='using stats.lognorm.fit(样本)'
plt.plot(np.sort(新样本),1-np.linspace(0,1,len(新样本)),label='using stats.norm.fit(log(样本)))
plt.legend()
plt.show()

Seaborn的kdeplot显示了以下内容:

导入seaborn作为sns
bw=1500
sns.kdeplot(samples,bw=bw,label='givesamples')
sns.kdeplot(奇怪的样本,bw=bw,label='using stats.lognorm.fit(样本)'))
sns.kdeplot(新样本,bw=bw,label='using stats.norm.fit(log(samples)))
plt.xlim(-500045000)
plt.show()

PS:问题似乎是使用有限的样本拟合3个参数效果不太好。您可以强制
lognorm.fit
使用
loc=0
,这样可以找到更合理的参数。
loc
参数只是用该量移动样本;通常,
loc=0
是更好的选择

std, loc, scale = stats.lognorm.fit(samples, floc=0) # 0.9720253999925554, 0.0, 4043.3848507251523
您还可以提供初始猜测,而不是使用
floc
强制执行
loc
。这看起来更好:

std, loc, scale = stats.lognorm.fit(samples, loc=0) # 1.0527481074345748, 203.08004314932137, 3712.4903893865644