def dropdf_copy(df):
    df = df.drop('y',axis=1)

def dropdf_inplace(df):
    df.drop('y',axis=1,inplace=True)    

def changecell(df):
    df['y'][0] = 99


x = pd.DataFrame({'x': [1,2],'y': [20,31]})

x
Out[204]: 
   x   y
0  1  20
1  2  31

dropdf_copy(x)

x
Out[206]: 
   x   y
0  1  20
1  2  31

changecell(x)

x
Out[208]: 
   x   y
0  1  99
1  2  31

En el ejemplo anterior, dropdf () no modifica el marco de datos original x mientras que changecell () modifica x. Sé que si agrego el cambio menor a changecell (), no cambiará x.

def changecell(df):
    df = df.copy()
    df['y'][0] = 99

No creo que sea muy elegante incluir df = df.copy() en cada función que escribo.

Preguntas

1) ¿En qué circunstancias los pandas cambian el marco de datos original y cuándo no? ¿Alguien puede darme una regla generalizable clara? Sé que puede tener algo que ver con la mutabilidad Vs la inmutabilidad, pero no se explica claramente en stackoverflow.

2) ¿Numpy se comporta de manera similar o es diferente? ¿Qué pasa con otros objetos de Python?

PD: He investigado en stackoverflow pero no pude encontrar una regla generalizable clara para este problema.

2
GeorgeOfTheRF 29 oct. 2017 a las 21:17

2 respuestas

La mejor respuesta

Por defecto, Python pasa por referencia. Solo si se hace una copia explícita en la función como asignación o se usa una función copy (), el objeto original pasado no cambia.

Ejemplo con copia explícita:

#1. Assignment 
def dropdf_copy1(df):

    df = df.drop('y',axis=1)
#2. copy()
def dropdf_copy2(df):
    df = df.copy() 
    df.drop('y',axis=1,inplace = True)

Si no se realiza una copia explícita, se cambia el objeto original pasado.

def dropdf_inplace(df):
    df.drop('y',axis=1,inplace = True)
1
GeorgeOfTheRF 1 nov. 2017 a las 07:14

Nada que ver con los pandas. Es un problema de variables locales / globales en valores mutables. en dropdf, establece df como una variable local.

Lo mismo con las listas:

def global_(l):
    l[0]=1

def local_(l):
    l=l+[0]  

En la segunda función, será lo mismo si escribiste:

def local_(l):
    l2=l+[0]

Para que no afecte a l.

Aquí el ejemplo de tutor de Python qué calza qué sucede.

0
B. M. 29 oct. 2017 a las 18:51