¿Los pandas describen vs scipy.stats percentileofscore con NaN?

Estoy teniendo una situación extraña, donde pd.describe me da marcadores de percentiles que no están de acuerdo con scipy.stats percentileofscore, debido a los NaN, creo.

Mi df es:

f_recommend 0 3.857143 1 4.500000 2 4.458333 3 NaN 4 3.600000 5 NaN 6 4.285714 7 3.587065 8 4.200000 9 NaN 

Cuando ejecuto df.describe(percentiles=[.25, .5, .75]) obtengo:

  f_recommend count 7.000000 mean 4.069751 std 0.386990 min 3.587065 25% 3.728571 50% 4.200000 75% 4.372024 max 4.500000 

Obtengo los mismos valores cuando corro con NaN eliminado.

Sin embargo, cuando quiero buscar un valor específico, cuando ejecuto scipy.stats.percentileofscore(df['f_recommend'], 3.61, kind = 'mean') obtengo: percentil 28 con NaN y 20 sin.

¿Alguna idea para explicar esta discrepancia?

ETA:

No creo que el problema sea que estamos calculando percentiles de manera diferente. Porque eso solo importa cuando estás calculando percentiles de los mismos 2 números de diferentes maneras. Pero aquí, describa da 25 percentil como 3.72. Así que no hay absolutamente ninguna manera de que 3.61 pueda ser el percentil 28. Ninguna de las fórmulas debe dar eso.

En particular, cuando uso la descripción en los 6 valores sin NaN, obtengo los mismos valores, por lo que eso es ignorar NaN, lo cual está bien. Pero cuando ejecuto el percentil de puntuación sin el NaN, obtengo un número que no coincide.

ETA 2:

Ejemplo más simple:

 In [48]: d = pd.DataFrame([1,2,3,4,5,6,7]) In [49]: d.describe() Out[49]: 0 count 7.000000 mean 4.000000 std 2.160247 min 1.000000 25% 2.500000 50% 4.000000 75% 5.500000 max 7.000000 In [50]: sp.stats.percentileofscore(d[0], 2.1, kind = 'mean') Out[50]: 28.571428571428573 

el argumento “tipo” no importa porque 2.1 es único.

scipy.stats.percentileofscore no ignora nan , ni comprueba el valor y lo maneja de alguna manera especial. Es solo otro valor de punto flotante en sus datos. Esto significa que el comportamiento de percentileofscore con datos que contienen nan no está definido, debido al comportamiento de nan en las comparaciones:

 In [44]: np.nan > 0 Out[44]: False In [45]: np.nan < 0 Out[45]: False In [46]: np.nan == 0 Out[46]: False In [47]: np.nan == np.nan Out[47]: False 

Esos resultados son todos correctos, así es como se supone que debe comportarse nan . Pero eso significa que, para saber cómo percentileofscore maneja nan , tienes que saber cómo hace el código las comparaciones. Y ese es un detalle de implementación que no debería tener que saber, y en el que no puede confiar para ser el mismo en futuras versiones de scipy.

Si investigas el comportamiento de percentfileofscore , encontrarás que se comporta como si nan fuera infinito. Por ejemplo, si reemplaza nan por un valor mayor que cualquier otro valor en la entrada, obtendrá los mismos resultados:

 In [53]: percentileofscore([10, 20, 25, 30, np.nan, np.nan], 18) Out[53]: 16.666666666666664 In [54]: percentileofscore([10, 20, 25, 30, 999, 999], 18) Out[54]: 16.666666666666664 

Desafortunadamente, no puedes confiar en este comportamiento. Si la implementación cambia en el futuro, nan podría terminar comportándose como infinito negativo o tener algún otro comportamiento no especificado.

La solución a este "problema" es simple: no dé un percentileofscore los valores de nan . Tendrás que limpiar tus datos primero. Tenga en cuenta que esto puede ser tan simple como:

 result = percentileofscore(a[~np.isnan(a)], score) 

La respuesta es muy simple.

No existe una fórmula universalmente aceptada para calcular percentiles, en particular cuando sus datos contienen vínculos o cuando no se pueden dividir perfectamente en grupos de igual tamaño.

Por ejemplo, eche un vistazo a la documentación en R ¡Hay más de siete tipos de fórmulas! https://stat.ethz.ch/R-manual/R-devel/library/stats/html/quantile.html

Al final, todo se reduce a comprender qué fórmula se usa y si las diferencias son lo suficientemente grandes como para ser un problema en su caso.