Estoy creando una función. Una entrada de esta función será un marco de datos de panda y una de sus tareas es realizar algunas operaciones con dos variables de este marco de datos. Estas dos variables no son fijas y quiero tener la libertad de determinarlas utilizando parámetros como entradas de la función fun.

Por ejemplo, suponga que en algún momento las variables que quiero usar son 'var1' y 'var2' (pero en otro momento, podría querer usar otras dos variables). Suponga que estas variables toman valores 1,2,3,4 y quiero reducir df haciendo var1 == 1 y var2 == 1. Mis funciones son así

def fun(df , var = ['input_var1', 'input_var2'] , val):
    df = df.rename(columns={  var[1] : 'aux_var1 ', var[2]:'aux_var2'})

    # Other operations
    df  = df.loc[(df.aux_var1 == val ) & (df.aux_var2 == val )] 
    # end of operations

    # recover 
    df = df.rename(columns={ 'aux_var1': var[1] ,'aux_var2': var[2]})
    return df 

Cuando uso la función fun, tengo el error

fun(df, var = ['var1','var2'], val = 1)
IndexError: list index out of range

En realidad, quiero hacer otras operaciones más complejas y no describí estas operaciones para no extender la pregunta. Quizás el simple ejemplo anterior tiene una solución que no necesita cambiar el nombre de las variables. Pero tal vez esta solución no funcione con las operaciones que realmente quiero hacer. Entonces, primero, necesariamente me gustaría corregir el error al cambiar el nombre de las variables. Si desea dar otra solución más elegante que no necesita cambiar de nombre, se lo agradezco también, pero le agradeceré si, además de la solución elegante, me ofrece la solución para cambiar el nombre.

2
Fam 29 sep. 2019 a las 09:29

3 respuestas

La mejor respuesta

Las escuchas de Python están indexadas a cero, es decir, el índice del primer elemento es 0. Simplemente cambie las líneas:

df = df.rename(columns={  var[1] : 'aux_var1 ', var[2]:'aux_var2'})

df = df.rename(columns={ 'aux_var1': var[1] ,'aux_var2': var[2]})

Para

df = df.rename(columns={  var[0] : 'aux_var1 ', var[1]:'aux_var2'})

df = df.rename(columns={ 'aux_var1': var[0] ,'aux_var2': var[1]})

Respectivamente

3
Quickbeam2k1 29 sep. 2019 a las 06:34

Como se ha mencionado en otras respuestas, el error que está recibiendo se debe a la indexación 0 de las listas de Python, es decir, si desea acceder al primer elemento de la lista var, lo hace tomando el { Índice {X1}} en lugar del índice 1: var[0].

Sin embargo, con respecto al tema del cambio de nombre, puede realizar el filtrado del marco de datos de pandas sin ningún cambio de nombre de columna. Puedo ver que está accediendo a la columna como un atributo del marco de datos, sin embargo, puede lograr lo mismo mediante el uso del método __getitem__, que se usa más comúnmente con corchetes, p. Ej. df[var[0]].

Si desea tener más generalidad sobre su función sin que ocurra ningún cambio de nombre, puedo sugerir esto:

from functools import reduce

def fun(df , var, val):
    _sub = reduce(
                  lambda x, y: x & (df[y] == val), 
                  var, 
                  pd.Series([True]*df.shape[0])
                 )
    return df[_sub]

Esto funcionará con cualquier número de variables de columna de entrada. Espero que esto sirva de inspiración para sus operaciones más complicadas que tiene la intención de hacer.

2
Richard Nemeth 29 sep. 2019 a las 06:50

En este caso, está accediendo a var[2] pero una lista de 2 elementos en Python tiene los elementos 0 y 1. El elemento 2 no existe y, por lo tanto, el acceso está fuera de rango.

3
Simon 29 sep. 2019 a las 06:34
58152853