2017-01-12 2 views
3

Je veux tracer un cdf de données sur un graphique de lognormale, comme indiqué ci-dessous:Python Lognormal Probabilités Terrain

enter image description here

Je veux que les échelles des axes sur mon terrain pour ressembler à ça, seulement renversé (avec probabilité sur l'axe des x). Notez que l'axe des Y ci-dessus n'est PAS simplement une échelle logarithmique. Aussi je ne suis pas sûr pourquoi l'axe des x ci-dessus répète 1-9 au lieu d'aller à 10-99 etc, mais ignorer cette partie.

Voici ce que j'ai jusqu'à présent. J'utilise la méthode pour faire un CDF comme Outlined here

mu, sigma = 3., 1. # mean and standard deviation 
data = np.random.lognormal(mu, sigma, 1000) 

#Make CDF 
dataSorted = np.sort(data) 
dataCdf = np.linspace(0,1,len(dataSorted)) 

plt.plot(dataCdf, dataSorted) 
plt.gca().set_yscale('log') 
plt.xlabel('probability') 
plt.ylabel('value') 

enter image description here

Maintenant je dois juste une façon d'échelle mon axe x comme l'axe y est sur l'image ci-dessus.

+1

C'est ce que vous avez besoin: [Tracer des axes logarithmiques avec matplotlib en python] (http://stackoverflow.com/questions/773814/plot-logarithmic-axes-with-matplotlib-in -python)? – Lucas

+1

N'est-ce pas évident comment vous pouvez faire de l'axe x logarithmique de votre code actuel? 'plt.gca(). set_yscale ('log')' -> 'plt.gca(). set_xscale ('log')' –

+0

L'échelle x (ou y-scale dans les exemples d'axes) n'est pas logarithmique. J'ai changé l'image des axes de l'exemple pour plus de clarté. Les valeurs de probabilité «moyennes» sont proches les unes des autres, les grandes/petites étant plus éloignées. C'est comme son logarithmique jusqu'à 0.5 et "inversement" logarithmique de 0.5 à 1 – hm8

Répondre

2

Une façon de résoudre ce problème consiste à utiliser une échelle logarithmique symétrique, appelée symlog. Symlog est un graphe logarithmique qui se comporte linéairement dans une plage de 0 (où un graphe de log normal afficherait infiniment plusieurs dizaines d'années) de sorte qu'un graphe logarithmique traversant 0 est réellement possible.

Symlog peut être défini dans matplotlib en utilisant ax.set_xscale('symlog', linthreshx=0.1)linthreshx indique la plage linéaire autour de zéro. Comme dans ce cas, nous voulons que le centre du graphique soit à 0.5 au lieu de 0, nous pouvons réellement tracer deux graphiques et les coller ensemble. Afin d'obtenir le résultat souhaité, vous pouvez maintenant jouer avec les graduations à afficher, ainsi qu'avec le paramètre linthreshx. Voici un exemple.

import matplotlib.pyplot as plt 
import numpy as np 
import matplotlib.ticker 
mu, sigma = 3., 1. # mean and standard deviation 
data = np.random.lognormal(mu, sigma, 1000) 

#Make CDF 
dataSorted = np.sort(data) 
dataCdf = np.linspace(0,1,len(dataSorted)) 

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True) 
plt.subplots_adjust(wspace=0.00005) 
ax1.plot(dataCdf[:len(dataCdf)/2], dataSorted[:len(dataCdf)/2]) 
ax2.plot(dataCdf[len(dataCdf)/2:]-1, dataSorted[len(dataCdf)/2:]) 

ax1.set_yscale('log') 
ax2.set_yscale('log') 

ax1.set_xscale('symlog', linthreshx=0.001) 
ax2.set_xscale('symlog', linthreshx=0.001) 

ax1.set_xlim([0.01, 0.5]) 
ax2.set_xlim([-0.5, -0.01]) 

ticks = np.array([0.01,0.1, 0.3]) 
ticks2 = ((1-ticks)[::-1])-1 
ax1.set_xticks(ticks) 
ax1.xaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter()) 
ax2.set_xticks(ticks2) 
ax2.xaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter()) 
ax2.set_xticklabels(ticks2+1) 

ax1.spines["right"].set_visible(False) 
ax2.spines["left"].set_visible(False) 
ax1.yaxis.set_ticks_position('left') 
ax2.yaxis.set_ticks_position('right') 

ax1.set_xlabel('probability') 
ax1.set_ylabel('value') 

plt.savefig(__file__+".png") 
plt.show() 

enter image description here

+0

Comme il s'avère que ce n'est pas vraiment ce que je cherche. Une distribution log-normale devrait apparaître comme une ligne parfaitement droite sur le graphique. Mon interprétation de 'logarithmique jusqu'à 0.5 et "inversement" logarithmique de 0.5 à 1' doit être incorrecte. – hm8