pandas 2.2 se lanzó el 22 de enero de 2024. Echemos un vistazo a las cosas que presenta esta versión y cómo nos ayudará a mejorar nuestras cargas de trabajo de pandas. Incluye un montón de mejoras que mejorarán la experiencia del usuario.
pandas 2.2 trajo algunas mejoras adicionales que se basan en el ecosistema Apache Arrow. Además, agregamos obsolescencias para los cambios que son necesarios para que Copiar en escritura sea el valor predeterminado en pandas 3.0. Profundicemos en lo que esto significa para usted. Analizaremos los cambios más importantes en detalle.
Soy parte del equipo central de pandas. Soy un ingeniero de código abierto para Enroscado donde trabajo en Dask, incluida la mejora de la integración de pandas.
Soporte mejorado de PyArrow
Introducimos DataFrame respaldado por PyArrow en pandas 2.0 y continuamos mejorando la integración desde entonces para permitir una integración perfecta con la API de pandas. pandas tiene descriptores de acceso para ciertos tipos de caracteres que permiten operaciones especializadas, como el descriptor de acceso de cadena, que proporciona muchos métodos de cadena. Históricamente, las listas y estructuras se representaban como tipo de objeto NumPy, lo que hacía que trabajar con ellas fuera bastante engorroso. El backend Arrow dtype ahora permite accesos personalizados para listas y estructuras, lo que hace que trabajar con estos objetos sea mucho más fácil.
Veamos un ejemplo:
import pyarrow as paseries = pd.Series(
[
{"project": "pandas", "version": "2.2.0"},
{"project": "numpy", "version": "1.25.2"},
{"project": "pyarrow", "version": "13.0.0"},
],
dtype=pd.ArrowDtype(
pa.struct([
("project", pa.string()),
("version", pa.string()),
])
),
)
Esta es una serie que contiene un diccionario en cada fila. Anteriormente, esto solo era posible con el tipo de objeto NumPy y acceder a los elementos desde estas filas requería iterar sobre ellas. El struct El descriptor de acceso ahora permite el acceso directo a ciertos atributos:
series.struct.field("project")0 pandas
1 numpy
2 pyarrow
Name: project, dtype: string[pyarrow]
La próxima versión traerá un CategoricalAccessor basado en tipos de flechas.
Integración del controlador Apache ADBC
Históricamente, los pandas dependían de SqlAlchemy para leer datos de una base de datos Sql. Esto funcionó de manera muy confiable, pero fue muy lento. Alchemy lee los datos en filas, mientras que pandas tiene un diseño en columnas, lo que hace que la lectura y el movimiento de los datos a un DataFrame sea más lento de lo necesario.
El Controlador ADBC del proyecto Apache Arrow permite a los usuarios leer datos en un diseño de columnas, lo que aporta enormes mejoras de rendimiento. Lee los datos y los almacena en una tabla Arrow, que se utiliza para convertir a un DataFrame de pandas. Puede realizar esta conversión con copia cero, si configura dtype_backend="pyarrow" para read_sql.
Veamos un ejemplo:
import adbc_driver_postgresql.dbapi as pg_dbapidf = pd.DataFrame(
[
[1, 2, 3],
[4, 5, 6],
],
columns=['a', 'b', 'c']
)
uri = "postgresql://postgres:postgres@localhost/postgres"
with pg_dbapi.connect(uri) as conn:
df.to_sql("pandas_table", conn, index=False)
# for round-tripping
with pg_dbapi.connect(uri) as conn:
df2 = pd.read_sql("pandas_table", conn)
El controlador ADBC actualmente es compatible con Postgres y Sqlite. Recomendaría a todos que cambien a este controlador si usan Postgres, el controlador es significativamente más rápido y evita por completo los viajes de ida y vuelta a través de objetos de Python, preservando así los tipos de bases de datos de manera más confiable. Esta es la característica que personalmente me entusiasma más.
Agregar case_when a la API de pandas
Al pasar de Sql a pandas, los usuarios a menudo pasan por alto la sintaxis de casos en los que se proporciona una forma fácil y limpia de crear nuevas columnas de forma condicional. pandas 2.2 agrega una nueva case_when método, que se define en una serie. Funciona de manera similar a lo que hace Sql.
Veamos un ejemplo:
df = pd.DataFrame(dict(a=[1, 2, 3], b=[4, 5, 6]))default=pd.Series('default', index=df.index)
default.case_when(
caselist=[
(df.a == 1, 'first'),
(df.a.gt(1) & df.b.eq(5), 'second'),
],
)
El método toma una lista de condiciones que se evalúan secuencialmente. Luego, el nuevo objeto se crea con esos valores en las filas donde la condición se evalúa como Verdadera. El método debería facilitarnos significativamente la creación de columnas condicionales.
Copiar en escrito
La copia en escritura se introdujo inicialmente en pandas 1.5.0. El modo se convertirá en el comportamiento predeterminado con 3.0, que con suerte será la próxima versión de Pandas. Esto significa que tenemos que llevar nuestro código a un estado en el que cumpla con las reglas de Copia en escritura. pandas 2.2 introdujo advertencias de desaprobación para operaciones que cambiarán el comportamiento.
df = pd.DataFrame({"x": [1, 2, 3]})df["x"][df["x"] > 1] = 100
Esto ahora generará un FutureWarning.
FutureWarning: ChainedAssignmentError: behaviour will change in pandas 3.0!
You are setting values through chained assignment. Currently this works in certain cases, but when
using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to
update the original DataFrame or Series, because the intermediate object on which we are setting
values will behave as a copy. A typical example is when you are setting values in a column of a
DataFrame, like:df["col"][row_indexer] = value
Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and
ensure this keeps updating the original `df`.
escribí una publicación anterior que entra en más detalles sobre cómo puede migrar su código y qué esperar. Hay un modo de advertencia adicional para Copiar en escritura que generará advertencias para todos los casos que cambien el comportamiento:
pd.options.mode.copy_on_write = "warn"
La mayoría de esas advertencias son sólo ruido para la mayoría de los usuarios de pandas, razón por la cual están ocultas detrás de una opción.
pd.options.mode.copy_on_write = "warn"df = pd.DataFrame({"a": [1, 2, 3]})
view = df["a"]
view.iloc[0] = 100
Esto generará una larga advertencia explicando qué cambiará:
FutureWarning: Setting a value on a view: behaviour will change in pandas 3.0.
You are mutating a Series or DataFrame object, and currently this mutation will
also have effect on other Series or DataFrame objects that share data with this
object. In pandas 3.0 (with Copy-on-Write), updating one Series or DataFrame object
will never modify another.
El breve resumen de esto es: Actualización view nunca se actualizará df, sin importar qué operación se utilice. Lo más probable es que esto no sea relevante para la mayoría.
Recomendaría habilitar el modo y verificar las advertencias brevemente, pero no prestarles demasiada atención si se siente cómodo sin depender de actualizar dos objetos diferentes a la vez.
Recomendaría consultar el guía de migración para copia en escritura que explica los cambios necesarios con más detalle.
Actualizando a la nueva versión
Puedes instalar la nueva versión de pandas con:
pip install -U pandas
O:
mamba install -c conda-forge pandas=2.2
Esto le dará la nueva versión en su entorno.
Conclusión
Hemos analizado un par de mejoras que mejorarán el rendimiento y la experiencia del usuario en ciertos aspectos de pandas. Las nuevas funciones más interesantes vendrán en pandas 3.0, donde la función Copiar en escritura estará habilitada de forma predeterminada.
Gracias por leer. No dude en comunicarse para compartir sus pensamientos y comentarios.