Ajustement de la distribution log-normale dans R vs. SciPy

10

J'ai adapté un modèle lognormal utilisant R avec un ensemble de données. Les paramètres résultants étaient:

meanlog = 4.2991610 
sdlog = 0.5511349

J'aimerais transférer ce modèle sur Scipy, que je n'ai jamais utilisé auparavant. En utilisant Scipy, j'ai pu obtenir une forme et une échelle de 1 et 3,1626716539637488e + 90 - des nombres très différents. J'ai également essayé d'utiliser l'exp du meanlog et du sdlog mais continue à obtenir un graphique bizarre.

J'ai lu tous les documents que je peux sur scipy et je suis toujours confus quant à la signification des paramètres de forme et d'échelle dans ce cas. Serait-il juste logique de coder la fonction moi-même? Cela semble cependant sujet à des erreurs, car je suis nouveau sur scipy.

SCIPY Lognormal (BLUE) contre R Lognormal (RED): Scipy Lognormal (BLUE) contre R Lognormal (RED)

Avez-vous des idées sur la direction à prendre? Les données sont très bien adaptées au modèle R, d'ailleurs, si elles ressemblent à quelque chose d'autre en Python, n'hésitez pas à les partager.

Je vous remercie!

Mettre à jour:

Je lance Scipy 0.11

Voici un sous-ensemble des données. L'échantillon réel est de 38k +, avec une moyenne de 81,53627:

Sous-ensemble:

x
[60, 170, 137, 138, 81, 140, 78, 46, 1, 168, 138, 148, 145, 35, 82, 126, 66, 147, 88, 106, 80, 54, 83, 13, 102, 54, 134, 34]
numpy.mean (x)
99.071428571428569

Alternativement:

Je travaille sur une fonction pour capturer le pdf:

def lognoral(x, mu, sigma):
    a = 1 / (x * sigma * numpy.sqrt(2 * numpy.pi) )
    b = - (numpy.log(x) - mu) ^ 2 / (2 * sigma ^ 2)
    p = a * numpy.exp(b)
    return p

Cependant, cela me donne les chiffres suivants (j'en ai essayé plusieurs au cas où j'aurais mélangé le sens de sdlog et meanlog):

>>> lognormal(54,4.2991610, 0.5511349)
0.6994656085799437
 >>> lognormal(54,numpy.exp(4.2991610), 0.5511349)
0.9846125119455129
>>> lognormal(54,numpy.exp(4.2991610), numpy.exp(0.5511349))
0.9302407837304372

Des pensées?

Mettre à jour:

relance avec la suggestion "UPQuark":

forme, loc, échelle (1.0, 50.03445923295007, 19.074457156766517)

La forme du graphique est cependant très similaire, le pic se situant autour de 21.

Lillian Milagros Carrasquillo
la source
Ces questions et réponses peuvent vous aider: stackoverflow.com/questions/8747761/…
jbowman
Merci, j'ai trouvé ça et appris le "fit" avec le lognormal. Cependant, mes questions sont pourquoi devrais-je obtenir des distributions si différentes?
Lillian Milagros Carrasquillo
Utilisez-vous SciPy 0.9? Pourriez-vous également publier vos données ou un sous-ensemble de celles-ci?
jbowman
Mise à jour! C'est Scipy 0.11 au fait. Donc les bugs dont j'ai lu ne devraient pas être pertinents;)
Lillian Milagros Carrasquillo

Réponses:

11

Je me suis frayé un chemin à travers le code source, pour arriver à l'interprétation suivante de la routine lognormale scipy.

xlocscaleLognormal(σ)

où est le paramètre "forme". σ

L'équivalence entre les paramètres scipy et le paramètre R est la suivante:

loc - Aucun équivalent, cela est soustrait de vos données afin que 0 devienne l'infimum de la plage des données.

échelle - , où est la moyenne du log de la variable. (Lors de l'ajustement, vous utilisez généralement la moyenne de l'échantillon du journal des données.) μexpμμ

forme - l'écart type du logarithme de la variable.

J'ai appelé lognorm.pdf(x, 0.55, 0, numpy.exp(4.29))où les arguments sont (x, forme, loc, échelle) respectivement, et généré les valeurs suivantes:

x pdf

10 0.000106

20 0,002275

30 0,006552

40 0,009979

50 0,114557

60 0,113479

70 0,103327

80 0,008941

90 0,007494

100 0,006155

qui semblent correspondre assez bien à votre courbe R.

jbowman
la source
Merci, @JBowman, c'est exactement l'explication dont j'avais besoin et la sortie est précisément ma distribution.
Lillian Milagros Carrasquillo
8

La distribution lognormale dans SciPy s'inscrit dans le cadre général de toutes les distributions dans SciPy. Ils ont tous un mot-clé d'échelle et d'emplacement (par défaut 0 et 1 s'ils ne sont pas explicitement fournis). Cela permet à toutes les distributions d'être déplacées et mises à l'échelle de leur spécification normalisée avec des implications claires pour les statistiques de la distribution. Les distributions ont généralement aussi un ou plusieurs paramètres de "forme" (bien que certains, comme la distribution normale, n'aient pas besoin de paramètres supplémentaires).

Bien que cette approche générale unifie bien toutes les distributions, pour lognormal, elle peut créer une certaine confusion en raison de la façon dont d'autres packages définissent les paramètres. Pourtant, il est très simple de faire correspondre n'importe quelle distribution lognormale si vous voulez direlog (la moyenne de la distribution sous-jacente) et sdlog (l'écart-type de la distribution sous-jacente).

Tout d'abord, assurez-vous de définir le paramètre d'emplacement sur 0. Ensuite, définissez le paramètre de forme sur la valeur de sdlog. Enfin, définissez le paramètre d'échelle sur math.exp (meanlog). Ainsi, rv = scipy.stats.lognorm (0.5511349, scale = math.exp (4.2991610)) créera un objet de distribution dont le pdf correspond exactement à votre courbe générée par R. Comme x = numpy.linspace (0,180,1000); plot (x, rv.pdf (x)) vérifiera.

Fondamentalement, la distribution lognormale de SciPy est une généralisation de la distribution lognormale standard qui correspond exactement à la norme lors de la définition du paramètre d'emplacement sur 0.

Lorsque vous ajustez des données avec la méthode .fit, vous pouvez également utiliser des mots clés, f0..fn, floc et fshape pour maintenir fixe l'un des paramètres de forme, d'emplacement et / ou d'échelle et ne tenir que sur les autres variables. Pour la distribution lognormale, cela est très utile car généralement vous savez que le paramètre d'emplacement doit être fixé à 0. Ainsi, scipy.stats.lognorm.fit (jeu de données, floc = 0) renverra toujours le paramètre d'emplacement à 0 et ne fera varier que l'autre paramètres de forme et d'échelle.

Travis Oliphant
la source
3

L'ajustement log-normal Scipy renvoie la forme, l'emplacement et l'échelle. Je viens d'exécuter ce qui suit sur un tableau d'exemples de données de prix:

shape, loc, scale = st.lognorm.fit(d_in["price"])

Cela me donne des estimations raisonnables de 1,0, 0,09, 0,86, et lorsque vous le tracez, vous devez prendre en compte les trois paramètres.

Le paramètre de forme est l'écart-type de la distribution normale sous-jacente, et l'échelle est l'exponentielle de la moyenne de la normale.

J'espère que cela t'aides.

upquark
la source
Merci d'avoir répondu! Une fois que j'ai ces valeurs (loc, échelle, forme), j'essaie de trouver le pdf (x) pour chaque x qui m'intéresse (ici ce sont des valeurs de 0 à 180, exclusives). scipy.stats.lognorm.pdf (i, loc, échelle, forme) Cependant, en les traçant, j'obtiens l'intrigue ci-dessus.
Lillian Milagros Carrasquillo
OK, je vous ai vu mentionner la forme et l'échelle uniquement, c'est pourquoi j'ai mentionné qu'il y a trois paramètres renvoyés par défaut de fit (). Vous avez également dit que vous ne comprenez pas ce que signifient les paramètres de forme et d'échelle, et j'ai essayé de répondre à cela. Je n'ai jamais eu les valeurs absurdes de retour d'ajustement lognormal comme dans votre cas, quel est le paramètre d'emplacement?
upquark
Je viens de mettre à jour la question pour y répondre. Merci d'y avoir pensé.
Lillian Milagros Carrasquillo du
Appelez scipy.stats.lognorm.pdf (x, forme, loc, échelle) au lieu de scipy.stats.lognorm.pdf (i, loc, échelle, forme).
upquark
Merci, upquark, je l'ai fait aussi avec des résultats similaires. La forme globale du graphique continue d'être très différente des résultats attendus donnant dans R. Ressemble à une distribution totalement différente de celle dans R, en fait.
Lillian Milagros Carrasquillo
1

On dirait que la distribution dans Scipy pour le lognormal n'est pas la même que dans R, ou généralement, pas la même que la distribution que je connais. John D Cook a abordé ce sujet: http://www.johndcook.com/blog/2010/02/03/statistical-distributions-in-scipy/ http://www.johndcook.com/distributions_scipy.html

Cependant, je n'ai rien trouvé de concluant sur la façon d'utiliser une fonction de densité lognormale en Python. Si quelqu'un souhaite ajouter quelque chose, n'hésitez pas.

Ma solution jusqu'à présent est d'utiliser le pdf lognormal évalué entre 0 et 180 (exclusif), et utilisé comme dictionnaire dans le script python.

Lillian Milagros Carrasquillo
la source