4
votes

Quel est l'équivalent de fitdist et histfit en Python?

--- EXEMPLE ---

J'ai un ensemble de données (échantillon) qui contient 1 000 valeurs de dégâts ( les valeurs sont très petites ) dans un tableau à 1 dimension ( voir le fichier .json joint ) . L'échantillon semble suivre la distribution lognormale: Histogramme de l'ensemble de données (échantillon) et ses décomptes

--- PROBLÈME ET CE QUE J'AI DÉJÀ ESSAYÉ ---

J'ai essayé les suggestions de ce post Ajuster la distribution empirique à la distribution théorique avec Scipy (Python)? et ce post Scipy: ajustement lognormal pour adapter mes données par distribution lognormale. Aucun de ces travaux. :(

J'obtiens toujours quelque chose de très grand sur l'axe Y comme suit:

 tracer la distribution d'ajustement

Voici le code que j'ai utilisé en Python (et le fichier data.json peut être téléchargé depuis ici ):

fname = 'data.json';
sample = jsondecode(fileread(fname));

% fitting distribution
pd = fitdist(sample, 'lognormal')

% A combined command for plotting histogram and distribution
figure();
histfit(sample,40,"lognormal")

J'ai essayé l'autre type de distribution, mais quand j'essaye de tracer le résultat, l'axe Y est toujours trop grand et je ne peux pas tracer avec mon histogramme. Où ai-je échoué ???

J'ai également essayé la suggestion dans ma autre question: Utilisez la distribution lognormale scipy pour ajuster les données avec de petites valeurs, puis affichez-les dans matplotlib . Mais la valeur de la variable pdf_fitted est toujours trop grande.

--- ATTENDRE LE RÉSULTAT ---

En gros, ce que je veux, c'est comme ceci: p >

 enter image description here

Et voici le code Matlab que j'ai utilisé dans la capture d'écran ci-dessus:

from matplotlib import pyplot as plt
from scipy import stats as scistats
import json
with open("data.json", "r") as f:
  sample = json.load(f) # load data: a 1000 * 1 array with many small values( < 1e-6)
fig, axis = plt.subplots() # initiate a figure
N, nbins, patches = axis.hist(sample, bins = 40) # plot sample by histogram
axis.ticklabel_format(style = 'sci', scilimits = (-3, 4), axis = 'x') # make X-axis to use scitific numbers
axis.set_xlabel("Value")
axis.set_ylabel("Count")    
plt.show()

fig, axis = plt.subplots()
param = scistats.lognorm.fit(sample) # fit data by Lognormal distribution
pdf_fitted = scistats.lognorm.pdf(nbins, * param[: -2], loc = param[-2], scale = param[-1]) # prepare data for ploting fitted distribution
axis.plot(nbins, pdf_fitted) # draw fitted distribution on the same figure
plt.show()

Donc, si vous avez une idée de la commande équivalente de fitdist et histfit en Python / Scipy / Numpy / Matplotlib, veuillez la poster!

Merci beaucoup!


0 commentaires

3 Réponses :


0
votes

Essayez seaborn:

import seaborn as sns, numpy as np
sns.set(); np.random.seed(0)
x = np.random.randn(100)
ax = sns.distplot(x)

 entrez la description de l'image ici


1 commentaires

Salut, existe-t-il une solution qui n'utilise que le module "plus courant" comme scipy ou numpy?



3
votes

Essayez la bibliothèque distfit (ou fitdist).

https://erdogant.github.io/distfit/

dist = distfit(distr='lognorm')
dist.fit_transform(X)

Donc, dans votre cas, ce serait:

pip install distfit

import numpy as np

# Example data
X = np.random.normal(10, 3, 2000)
y = [3,4,5,6,10,11,12,18,20]

# From the distfit library import the class distfit
from distfit import distfit

# Initialize
dist = distfit()

# Search for best theoretical fit on your emperical data
dist.fit_transform(X)

# Plot
dist.plot()

# summay plot
dist.plot_summary()


2 commentaires

Comment définir floc = 0 en utilisant distfit? Je n'ai pas pu trouver cela dans les documents.


Il n'y a pas de paramètre d'entrée pour forcer cela à une valeur spécifiée. Dans le cas d'une distribution normale, le mot-clé location (loc) spécifie la moyenne. Le mot clé scale spécifie l'écart type. Mais d'autres distributions l'utilisent pour déplacer et / ou mettre à l'échelle la distribution. Il n'est donc peut-être pas si simple de les définir manuellement. La partie amusante est que vous n'avez pas à vous soucier de ces paramètres mais sont estimés pour vous avec distfit.



0
votes

J'ai essayé votre ensemble de données en utilisant la bibliothèque Openturns

x est la liste donnée dans votre fichier json.

axes = view.getAxes()
_ = axes[0].set_xlim(-0.6e-07, 2.8e-07)
plt.show()

 entrez la description de l'image ici

Si vous voulez les paramètres de la distribution

graph2 = ot.HistogramFactory().build(sample).drawPDF()
graph2.setColors(['blue'])
graph2.setLegends(["Histogram"])
graph2.add(graph)
View(graph2)

Vous pouvez construire l'histogramme de la même manière en appelant HistogramFactory, alors vous pouvez ajouter un graphique à un autre :

print(distribution)
>>> LogNormal(muLog = -16.5263, sigmaLog = 0.636928, gamma = 3.01106e-08)

et définissez les valeurs des limites si vous souhaitez zoomer

import openturns as ot
from openturns.viewer import View
import matplotlib.pyplot as plt

# first format your list x as a sample of dimension 1
sample = ot.Sample(x,1) 

# use the LogNormalFactory to build a Lognormal distribution according to your sample
distribution = ot.LogNormalFactory().build(sample)

# draw the pdf of the obtained distribution
graph = distribution.drawPDF()
graph.setLegends(["LogNormal"])
View(graph)
plt.show()

 entrez la description de l'image ici


0 commentaires