Marco de datos de Python: sum acumulativa de la columna hasta que se alcanza la condición y se devuelve el índice

Soy nuevo en Python y actualmente tengo un problema que no puedo resolver. Realmente espero que me puedas ayudar. El inglés no es mi idioma nativo, así que lo siento si no puedo expressme correctamente.

Digamos que tengo un dataframe simple con dos columnas:

index Num_Albums Num_authors 0 10 4 1 1 5 2 4 4 3 7 1000 4 1 44 5 3 8 Num_Abums_tot = sum(Num_Albums) = 30 

Necesito hacer una sum acumulativa de los datos en Num_Albums hasta que se Num_Albums una cierta condición. Registre el índice en el que se logra la condición y obtenga el valor correspondiente de Num_authors .

Ejemplo: sum acumulada de Num_Albums hasta que la sum sea igual a 50% ± 1/15 de 30 (-> 15 ± 2):

 10 = 15±2? No, then continue; 10+1 =15±2? No, then continue 10+1+41 = 15±2? Yes, stop. 

Condición alcanzada en el índice 2. Luego obtenga Num_Authors en ese índice: Num_Authors(2)=4

    Me gustaría ver si hay una función ya implementada en pandas , antes de empezar a pensar cómo hacerlo con un bucle de while / for …

    [Me gustaría especificar la columna de la que deseo recuperar el valor en el índice relevante (esto es útil cuando tengo, por ejemplo, 4 columnas y quiero sumr elementos en la columna 1, condición lograda = sí y luego obtener el valor correspondiente en la columna 2, luego haga lo mismo con las columnas 3 y 4)].

    Opción – 1:

    Podría calcular la sum acumulada utilizando la sum acumulada. Luego use np.isclose con su parámetro de tolerancia incorporado para verificar si los valores presentes en esta serie se encuentran dentro del umbral especificado de 15 +/- 2. Esto devuelve una matriz booleana.

    A través de np.flatnonzero , devuelva los valores ordinales de los índices para los cuales se cumple la condición True . Seleccionamos la primera instancia de un valor True .

    Finalmente, use .iloc para recuperar el valor del nombre de columna que necesita en función del índice calculado anteriormente.

     val = np.flatnonzero(np.isclose(df.Num_Albums.cumsum().values, 15, atol=2))[0] df['Num_authors'].iloc[val] # for faster access, use .iat 4 

    Al realizar np.isclose en la series convertida posteriormente en una matriz:

     np.isclose(df.Num_Albums.cumsum().values, 15, atol=2) array([False, False, True, False, False, False], dtype=bool) 

    Opt – 2:

    Use pd.Index.get_loc en la serie calculada de cumsum que también admite un parámetro de tolerance en el método nearest .

     val = pd.Index(df.Num_Albums.cumsum()).get_loc(15, 'nearest', tolerance=2) df.get_value(val, 'Num_authors') 4 

    Opt – 3:

    Use idxmax para encontrar el primer índice de un valor True para la máscara booleana creada después de las operaciones sub y abs en la serie cumsum :

     df.get_value(df.Num_Albums.cumsum().sub(15).abs().le(2).idxmax(), 'Num_authors') 4 

    Creo que puedes agregar directamente una columna con la sum acumulada como:

     In [3]: df Out[3]: index Num_Albums Num_authors 0 0 10 4 1 1 1 5 2 2 4 4 3 3 7 1000 4 4 1 44 5 5 3 8 In [4]: df['cumsum'] = df['Num_Albums'].cumsum() In [5]: df Out[5]: index Num_Albums Num_authors cumsum 0 0 10 4 10 1 1 1 5 11 2 2 4 4 15 3 3 7 1000 22 4 4 1 44 23 5 5 3 8 26 

    Y luego aplique la condición que desea en la columna de cumsum . Por ejemplo, puede usar where obtener la fila completa de acuerdo con el filtro. Configuración de la tolerancia tol :

     In [18]: tol = 2 In [19]: cond = df.where((df['cumsum']>=15-tol)&(df['cumsum']<=15+tol)).dropna() In [20]: cond Out[20]: index Num_Albums Num_authors cumsum 2 2.0 4.0 4.0 15.0 

    Esto incluso podría hacerse como el siguiente código:

     def your_function(df): sum=0 index=-1 for i in df['Num_Albums'].tolist(): sum+=i index+=1 if sum == ( " your_condition " ): return (index,df.loc([df.Num_Albums==i,'Num_authors'])) 

    Esto devolvería realmente una tupla de su índice y el valor correspondiente de Num_authors tan pronto como se scope la “condición”.

    o incluso podría ser devuelto como una matriz por

     def your_function(df): sum=0 index=-1 for i in df['Num_Albums'].tolist(): sum+=i index+=1 if sum == ( " your_condition " ): return df.loc([df.Num_Albums==i,'Num_authors']).index.values 

    No puedo averiguar la condición que mencionó de la sum acumulada como cuándo dejar de sumr, ¡así que lo mencioné como “su_condición” en el código!

    También soy nuevo, así que espero que ayude !!