Comprender inplace=True en pandas
En la pandas
biblioteca muchas veces hay una opción para cambiar el objeto in situ, como con la siguiente declaración...
df.dropna(axis='index', how='all', inplace=True)
Tengo curiosidad por saber qué se devuelve y cómo se maneja el objeto cuando inplace=True
se pasa y cuando inplace=False
.
¿Todas las operaciones se modifican self
cuando inplace=True
? ¿Y cuándo inplace=False
se crea inmediatamente un nuevo objeto new_df = self
y luego new_df
se devuelve?
Si está intentando cerrar una pregunta que alguien debería usar inplace=True
y no lo ha hecho, considere que el método replace() no funciona en Pandas DataFrame .
Cuando inplace=True
se pasa, se cambia el nombre de los datos en su lugar (no devuelve nada), por lo que usarías:
df.an_operation(inplace=True)
Cuando inplace=False
se pasa (este es el valor predeterminado, por lo que no es necesario), realiza la operación y devuelve una copia del objeto, por lo que usarías:
df = df.an_operation(inplace=False)
En los pandas, ¿inplace = True se considera dañino o no?
TLDR; Sí, así es.
inplace
, al contrario de lo que sugiere el nombre, a menudo no impide la creación de copias y (casi) nunca ofrece ningún beneficio de rendimiento.inplace
no funciona con encadenamiento de métodosinplace
puede provocarSettingWithCopyWarning
si se usa en una columna DataFrame y puede impedir que se realice la operación, lo que genera errores difíciles de depurar en el código.
Los puntos débiles anteriores son errores comunes para los principiantes, por lo que eliminar esta opción simplificará la API.
No recomiendo configurar este parámetro ya que sirve de poco . Vea este problema de GitHub que propone que el inplace
argumento quede obsoleto en toda la API.
Es un error común pensar que el uso inplace=True
conducirá a un código más eficiente u optimizado. En realidad, el uso de inplace=True
. Tanto la versión local como la fuera de lugar crean una copia de los datos de todos modos , y la versión local asigna automáticamente la copia.
inplace=True
Es un error común para los principiantes. Por ejemplo, puede desencadenarSettingWithCopyWarning
:
df = pd.DataFrame({'a': [3, 2, 1], 'b': ['x', 'y', 'z']})
df2 = df[df['a'] > 1]
df2['b'].replace({'x': 'abc'}, inplace=True)
# SettingWithCopyWarning:
# A value is trying to be set on a copy of a slice from a DataFrame
Llamar a una función en una columna DataFrame inplace=True
puede funcionar o no . Esto es especialmente cierto cuando se trata de indexación encadenada.
Como si los problemas descritos anteriormente no fueran suficientes, inplace=True
también dificulta el encadenamiento de métodos . Contraste el funcionamiento de
result = df.some_function1().reset_index().some_function2()
Opuesto a
temp = df.some_function1()
temp.reset_index(inplace=True)
result = temp.some_function2()
El primero se presta a una mejor organización y legibilidad del código.
Otra afirmación de respaldo es que la API set_axis
se cambió recientemente de modo que inplace
el valor predeterminado pasó de Verdadero a Falso. Ver GH27600 . ¡Buen trabajo desarrolladores!
La forma en que lo uso es
# Have to assign back to dataframe (because it is a new copy)
df = df.some_operation(inplace=False)
O
# No need to assign back to dataframe (because it is on the same copy)
df.some_operation(inplace=True)
CONCLUSIÓN:
if inplace is False
Assign to a new variable;
else
No need to assign
El inplace
parámetro:
df.dropna(axis='index', how='all', inplace=True)
en Pandas
y en general significa:
1. Pandas crea una copia de los datos originales.
2. ... hace algunos cálculos al respecto
3. ... asigna los resultados a los datos originales.
4. ... elimina la copia.
Como puede leer en el resto de mis respuestas más abajo, aún podemos tener buenas razones para usar este parámetro, es decir inplace operations
, , pero debemos evitarlo si podemos, ya que genera más problemas, como:
1. Su código será más difícil de depurar (en realidad, SettingwithCopyWarning significa advertirle sobre este posible problema)
2. Conflicto con el encadenamiento de métodos
Entonces, ¿hay algún caso en el que deberíamos usarlo todavía?
Definitivamente sí. Si utilizamos pandas o cualquier herramienta para manejar un gran conjunto de datos, podemos enfrentar fácilmente la situación en la que algunos grandes datos pueden consumir toda nuestra memoria. Para evitar este efecto no deseado podemos utilizar algunas técnicas como el encadenamiento de métodos :
(
wine.rename(columns={"color_intensity": "ci"})
.assign(color_filter=lambda x: np.where((x.hue > 1) & (x.ci > 7), 1, 0))
.query("alcohol > 14 and color_filter == 1")
.sort_values("alcohol", ascending=False)
.reset_index(drop=True)
.loc[:, ["alcohol", "ci", "hue"]]
)
lo que hace que nuestro código sea más compacto (aunque también más difícil de interpretar y depurar) y consume menos memoria ya que los métodos encadenados funcionan con los valores devueltos por el otro método, lo que da como resultado solo una copia de los datos de entrada. Podemos ver claramente que tendremos 2 veces el consumo de memoria de datos original después de estas operaciones.
O podemos usar inplace
un parámetro (aunque también es más difícil de interpretar y depurar), nuestro consumo de memoria será 2 x datos originales , pero nuestro consumo de memoria después de esta operación sigue siendo 1 x datos originales , lo que si alguien siempre ha trabajado con grandes conjuntos de datos sabe exactamente que puede ser un gran beneficio.
Conclusión final:
Evite el uso inplace
de parámetros a menos que no trabaje con una gran cantidad de datos y sea consciente de sus posibles problemas en caso de seguir utilizándolos.
Guárdalo en la misma variable.
data["column01"].where(data["column01"]< 5, inplace=True)
Guárdalo en una variable separada
data["column02"] = data["column01"].where(data["column1"]< 5)
Pero siempre puedes sobrescribir la variable.
data["column01"] = data["column01"].where(data["column1"]< 5)
Para su información: en defaultinplace = False