--- 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:
--- 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:
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.
En gros, ce que je veux, c'est comme ceci: p >
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!
3 Réponses :
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()
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.
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()
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()