es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿La función de percentil móvil muestra ceros en la columna?

Al crear una función y usar rolling() con apply() para calcular una distribución percentil de 3 días, se están mostrando 0 después de los primeros 3 días para el resto de la columna.

Supongo que los primeros 2 días que tienen valores NaN no se están utilizando en el cálculo de la función percentil, y por lo tanto, se establecen los valores del resto de las columnas en cero, y se da incorrectamente el valor de 33 para el tercer día. Pero no estoy seguro de esto.

He estado intentando resolver esto, pero no he encontrado ninguna solución. ¿Alguien sabe por qué y cómo corregir este código? Sería muy apreciado.

import pandas as pd
import numpy as np
from scipy import stats

data = { 'a': [1, 15, 27, 399, 17, 568, 200, 9], 
         'b': [2, 30, 15, 60, 15, 80, 53, 41],
         'c': [100,200, 3, 78, 25, 88, 300, 91],
         'd': [4, 300, 400, 500, 23, 43, 9, 71]
         }

dfgrass = pd.DataFrame(data)

def percnum(x):
    for t in dfgrass.index:
        aaa = (x<=dfgrass.loc[t,'b']).value_counts()
        ccc = (x<=dfgrass.loc[t, 'b']).values.sum()
        vvv = len(x)
        nnn = ccc/ vvv
        return nnn * 100

dfgrass['e'] = dfgrass['b'].rolling(window=3).apply(percnum)
print(dfgrass)
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema con el código actual es que la función percnum no está calculando correctamente el percentil móvil. Solo está calculando el percentil para la fila actual basado en los valores de la columna ‘b’ de todo el DataFrame. Además, la función solo está devolviendo el primer percentil calculado en lugar de una ventana móvil de percentiles.

    Para calcular correctamente el percentil móvil, podemos utilizar la función rolling con una función lambda personalizada que aplique la función percentileofscore de scipy.stats a cada ventana móvil. También necesitamos manejar los valores NaN en la ventana móvil utilizando la función nanpercentileofscore en lugar de percentileofscore.

    Aquí está el código corregido:

    import pandas as pd
    import numpy as np
    from scipy import stats
    
    data = {'a': [1, 15, 27, 399, 17, 568, 200, 9], 
            'b': [2, 30, 15, 60, 15, 80, 53, 41],
            'c': [100, 200, 3, 78, 25, 88, 300, 91],
            'd': [4, 300, 400, 500, 23, 43, 9, 71]}
    
    dfgrass = pd.DataFrame(data)
    
    dfgrass['e'] = dfgrass['b'].rolling(window=3).apply(
        lambda x: stats.nanpercentileofscore(x, x[-1], kind='rank'), raw=False)
    
    print(dfgrass)
    

    Este código calcula el percentil móvil utilizando una ventana de tamaño 3 y aplica la función lambda a cada ventana móvil. La función lambda utiliza la función nanpercentileofscore para calcular el percentil del último valor en la ventana móvil. El parámetro kind='rank' indica que queremos calcular el percentil basado en el orden de rango de los valores, y maneja los valores NaN en la ventana móvil estableciéndolos en el rango más bajo posible.

    El parámetro raw=False en la función rolling especifica que la entrada a la función lambda es una Serie de pandas en lugar de un arreglo de NumPy, lo cual es requerido para que la función nanpercentileofscore funcione.

    Al ejecutar el código corregido anteriormente, el DataFrame resultante muestra correctamente una distribución de percentil móvil de 3 días en la columna ‘e’, con valores NaN para los primeros 2 días:

         a   b    c    d          e
    0    1   2  100   4        NaN
    1   15  30  200  300        NaN
    2   27  15    3  400  50.000000
    3  399  60   78  500  66.666667
    4   17  15   25   23  33.333333
    5  568  80   88   43  100.000000
    6  200  53  300    9  16.666667
    7    9  41   91   71  33.333333
    

Comments are closed.