2017-06-17 1 views
2

J'ai un tableau que je veux convertir en centiles. Par exemple, dire que j'ai un tableau normalement distribué:Convertir un tableau en centiles

import numpy as np 
import matplotlib.pyplot as plt 

arr = np.random.normal(0, 1, 1000) 
plt.hist(arr) 

enter image description here

Pour chaque valeur dans ce tableau, je veux calculer le percentile de cette valeur (par exemple, 0 est le 50e percentile de la distribution ci-dessus donc 0 -> 0,5). Le résultat devrait être uniformément distribué puisque chaque centile devrait avoir un poids égal.

enter image description here

J'ai trouvé np.percentile mais cette fonction retourne une valeur donnée un tableau et quantile et ce que je dois revenir est un quantile donné un tableau et valeur.

Existe-t-il un moyen relativement efficace de le faire?

Répondre

2
from scipy.stats import percentileofscore 

# generate example data 
arr = np.random.normal(0, 1, 10) 

# pre-sort array 
arr_sorted = sorted(arr) 

# calculate percentiles using scipy func percentileofscore on each array element 
s = pd.Series(arr) 
percentiles = s.apply(lambda x: percentileofscore(arr_sorted, x)) 

vérifier que les résultats sont corrects:

df = pd.DataFrame({'data': s, 'percentiles': percentiles})  
df.sort_values(by='data') 

     data pcts 
3 -1.692881 10.0 
8 -1.395427 20.0 
7 -1.162031 30.0 
6 -0.568550 40.0 
9 0.047298 50.0 
5 0.296661 60.0 
0 0.534816 70.0 
4 0.542267 80.0 
1 0.584766 90.0 
2 1.185000 100.0 
0

est ici une approche alternative. Je pense que vous posez des questions sur l'estimation de la transformation intégrale de probabilité. Ce code produit une estimation assez fine, à savoir inverted_edf. Il procède en calculant des interpolations linéaires entre les points de SAMPLE à des valeurs distinctes. Ensuite, il calcule l'échantillon empirique df, et enfin inverted_edf.

Je dois mentionner que, même avec une taille d'échantillon de 1000 les centiles à la queue sont sujettes à la variabilité statistique considérable bien que pour 0,5 serait moins.

import statsmodels.distributions.empirical_distribution as edf 
from scipy.interpolate import interp1d 
import numpy as np 
import matplotlib.pyplot as plt 

SAMPLE = np.random.normal(0, 1, 1000) 
sample_edf = edf.ECDF(SAMPLE) 

slope_changes = sorted(set(SAMPLE)) 

sample_edf_values_at_slope_changes = [ sample_edf(item) for item in slope_changes] 
inverted_edf = interp1d(sample_edf_values_at_slope_changes, slope_changes) 

x = np.linspace(0.005, 1) 
y = inverted_edf(x) 
#~ plt.plot(x, y, 'ro', x, y, 'b-') 
plt.plot(x, y, 'b-') 
plt.show() 

p = 0.5 
print ('%s percentile:' % (100*p), inverted_edf(p)) 

Voici le graphique et la sortie textuelle pour deux exécutions.

PIT graph

50.0 percentile: -0.05917394517540461 
50.0 percentile: -0.0034011090849578695