Cómo restablecer el índice de un DataFrame de pandas
En este tutorial, aprenderá cómo restablecer un índice de Pandas DataFrame, las razones por las que podría querer hacerlo y los problemas que podrían ocurrir si no lo hace.
Antes de comenzar su viaje de aprendizaje, debe familiarizarse con cómo crear un DataFrame de pandas. Conocer la diferencia entre un DataFrame y una serie pandas también le resultará útil.
Además, es posible que desee utilizar la herramienta de análisis de datos Jupyter Notebook mientras trabaja en los ejemplos de este tutorial. Alternativamente, JupyterLab le brindará una experiencia de computadora portátil mejorada, pero siéntase libre de usar cualquier entorno Python que desee.
Como punto de partida, necesitará algunos datos. Para empezar, utilizará el archivo band_members.csv
incluido en los materiales descargables al que puede acceder haciendo clic en el siguiente enlace:
La siguiente tabla describe los datos de band_members.csv
con los que comenzará:
Column Name | PyArrow Data Type | Description |
---|---|---|
first_name |
string |
First name of member |
last_name |
string |
Last name of member |
instrument |
string |
Main instrument played |
date_of_birth |
string |
Member’s date of birth |
Como verás, los datos tienen detalles de los integrantes de la banda de rock The Beach Boys. Cada fila contiene información sobre sus distintos miembros, tanto pasados como presentes.
Nota: En caso de que nunca hayas oído hablar de The Beach Boys, son una banda de rock estadounidense formada a principios de los años 1960.
A lo largo de este tutorial, utilizará la biblioteca pandas para permitirle trabajar con DataFrames, así como la biblioteca PyArrow más nueva. La biblioteca PyArrow proporciona a pandas sus propios tipos de datos optimizados, que son más rápidos y consumen menos memoria que los tipos NumPy tradicionales que pandas usa de forma predeterminada.
Si está trabajando en la línea de comando, puede instalar pandas
y pyarrow
usando el comando único python -m pip install pandas pyarrow
. Si está trabajando en un Jupyter Notebook, debe usar !python -m pip install pandas pyarrow
. De todos modos, debe hacer esto dentro de un entorno virtual para evitar conflictos con las bibliotecas que utiliza en su entorno global.
Una vez que tenga las bibliotecas en su lugar, es hora de leer sus datos en un DataFrame:
>>> import pandas as pd
>>> beach_boys = pd.read_csv(
... "band_members.csv"
... ).convert_dtypes(dtype_backend="pyarrow")
Primero, usaste import pandas
para que la biblioteca estuviera disponible dentro de tu código. Para construir el DataFrame y leerlo en la variable beach_boys
, usaste la función read_csv()
de pandas, pasando band_members.csv
como el archivo a leer. Finalmente, al pasar dtype_backend="pyarrow"
a .convert_dtypes()
, convierte todas las columnas a tipos pyarrow
.
Si desea verificar que los tipos de datos pyarrow
realmente se están utilizando, entonces beach_boys.dtypes
satisfará su curiosidad:
>>> beach_boys.dtypes
first_name string[pyarrow]
last_name string[pyarrow]
instrument string[pyarrow]
date_of_birth string[pyarrow]
dtype: object
Como puede ver, cada tipo de datos contiene [pyarrow]
en su nombre.
Si desea analizar la información de la fecha a fondo, entonces debería analizar la columna date_of_birth
para asegurarse de que las fechas se lean como un tipo de fecha pyarrow
adecuado. Esto le permitiría analizar por días, meses o años específicos, etc., como se encuentra comúnmente en las tablas dinámicas.
La columna date_of_birth
no se analiza en este tutorial, por lo que el tipo de datos string
que se lee servirá. Más adelante, tendrás la oportunidad de perfeccionar tus habilidades con algunos ejercicios. Las soluciones incluyen el código de análisis de fecha si desea ver cómo se hace.
Ahora que el archivo se ha cargado en un DataFrame, probablemente querrás echarle un vistazo:
>>> beach_boys
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Al Jardine Guitar 03-Sep-1942
3 Bruce Johnston Bass 27-Jun-1942
4 Carl Wilson Guitar 21-Dec-1946
5 Dennis Wilson Drums 04-Dec-1944
6 David Marks Guitar 22-Aug-1948
7 Ricky Fataar Drums 05-Sep-1952
8 Blondie Chaplin Guitar 07-Jul-1951
Los DataFrames son estructuras de datos bidimensionales similares a hojas de cálculo o tablas de bases de datos. Un DataFrame de pandas puede considerarse un conjunto de columnas, y cada columna es una serie de pandas. Cada columna también tiene un encabezado, que es la propiedad name
de la Serie, y cada fila tiene una etiqueta, a la que se hace referencia como un elemento de su objeto de índice asociado.
El índice del DataFrame se muestra a la izquierda del DataFrame. No forma parte del archivo fuente original band_members.csv
, pero se agrega como parte del proceso de creación del DataFrame. Es este objeto de índice el que estás aprendiendo a restablecer.
El índice de un DataFrame es una columna adicional de etiquetas que le ayuda a identificar filas. Cuando se usa en combinación con encabezados de columna, le permite acceder a datos específicos dentro de su DataFrame. Las etiquetas de índice predeterminadas son una secuencia de números enteros, pero puedes usar cadenas para hacerlas más significativas. De hecho, puedes usar cualquier tipo hash para tu índice, pero los números enteros, cadenas y marcas de tiempo son los más comunes.
Nota: Aunque los índices son ciertamente útiles en pandas, una alternativa a los pandas es la nueva biblioteca Polars de alto rendimiento, que los elimina en favor de los números de fila. Esto puede resultar sorprendente, pero aparte de usarse para seleccionar filas o columnas, los índices no se usan con frecuencia al analizar DataFrames. Además, los números de fila siempre permanecen secuenciales cuando se agregan o eliminan filas en un Polars DataFrame. Este no es el caso de los índices en pandas.
Una vez superados estos preliminares, es hora de llevar tu Little Deuce Coupe a la playa, hacer un pop-up y aprender a navegar. Ahora investigará las principales formas de volver a indexar un DataFrame. Puede aplicar un objeto Index
directamente a la propiedad .index
del DataFrame, o usar el método .set_axis()
del DataFrame. Para empezar, utilizará el método .reset_index()
del DataFrame.
Cómo restablecer un índice de DataFrame de pandas con .reset_index()
El método DataFrame.reset_index()
, como su nombre indica, se utiliza para restablecer el índice de un DataFrame de pandas a su valor predeterminado. También puede utilizar este método para restablecer el MultiIndex
en su DataFrame si tiene uno. Aprenderá más sobre cómo restablecer índices múltiples más adelante.
Supongamos que ha estado realizando una limpieza de datos en su DataFrame y ha decidido ordenarlo alfabéticamente por first_name
. Puedes hacer esto usando .sort_values()
:
>>> beach_boys.sort_values(by="first_name")
first_name last_name instrument date_of_birth
2 Al Jardine Guitar 03-Sep-1942
8 Blondie Chaplin Guitar 07-Jul-1951
0 Brian Wilson Bass 20-Jun-1942
3 Bruce Johnston Bass 27-Jun-1942
4 Carl Wilson Guitar 21-Dec-1946
6 David Marks Guitar 22-Aug-1948
5 Dennis Wilson Drums 04-Dec-1944
1 Mike Love Saxophone 15-Mar-1941
7 Ricky Fataar Drums 05-Sep-1952
Si bien está contento de que la clasificación haya funcionado perfectamente, no está satisfecho con el estado actual de su índice. El índice ya no guarda ningún parecido con el orden actualizado de las filas.
Para solucionar este problema, su primera idea podría ser utilizar .reset_index()
con sus parámetros predeterminados, pero es posible que el resultado no sea el que desea:
>>> beach_boys.sort_values(by="first_name").reset_index()
index first_name last_name instrument date_of_birth
0 2 Al Jardine Guitar 03-Sep-1942
1 8 Blondie Chaplin Guitar 07-Jul-1951
2 0 Brian Wilson Bass 20-Jun-1942
3 3 Bruce Johnston Bass 27-Jun-1942
4 4 Carl Wilson Guitar 21-Dec-1946
5 6 David Marks Guitar 22-Aug-1948
6 5 Dennis Wilson Drums 04-Dec-1944
7 1 Mike Love Saxophone 15-Mar-1941
8 7 Ricky Fataar Drums 05-Sep-1952
Ahora tiene un nuevo índice predeterminado, que es una serie secuencial de números que comienza en cero y que define claramente el orden de las filas. Sin embargo, el índice original se mantuvo y se movió a una nueva columna que se llama confusamente index
. Esto puede ser aceptable si necesita devolver el DataFrame a su orden de clasificación original en el futuro, pero la mayoría de las veces, su inclusión solo desperdicia memoria. Generalmente querrás deshacerte de él.
Afortunadamente, esto es fácil de hacer. De forma predeterminada, .reset_index()
hace una copia del DataFrame original, aplica el índice predeterminado a esta segunda copia y le devuelve esa segunda copia. Esto significa que el índice del DataFrame original permanece sin cambios, por lo que no se le ha causado ningún daño.
Puede indicarle a .reset_index()
que elimine el índice original por completo y lo reemplace con uno nuevo predeterminado estableciendo su parámetro drop
en True
. También puede reasignar la referencia original al nuevo DataFrame. La versión actualizada será la única que exista a partir de este momento:
>>> beach_boys = (
... beach_boys.sort_values(by="first_name")
... .reset_index(drop=True)
... )
>>> beach_boys
first_name last_name instrument date_of_birth
0 Al Jardine Guitar 03-Sep-1942
1 Blondie Chaplin Guitar 07-Jul-1951
2 Brian Wilson Bass 20-Jun-1942
3 Bruce Johnston Bass 27-Jun-1942
4 Carl Wilson Guitar 21-Dec-1946
5 David Marks Guitar 22-Aug-1948
6 Dennis Wilson Drums 04-Dec-1944
7 Mike Love Saxophone 15-Mar-1941
8 Ricky Fataar Drums 05-Sep-1952
Ahora ha ordenado su DataFrame de la manera que desea. También reasignó la referencia original al nuevo DataFrame, lo que significa que la irritante columna index
se ha hundido sin dejar rastro.
Nota: El DataFrame original permanece sin cambios porque .reset_index()
, de forma predeterminada, devuelve una copia del DataFrame original. Puede establecer el parámetro inplace
en True
para cambiar el DataFrame original.
Con el tiempo, los desarrolladores de pandas han diseñado la mayoría de los métodos para devolver copias de DataFrame de forma predeterminada, de modo que cualquier análisis incorrecto pueda rehacerse correctamente fácilmente. Si cada método actualizara el DataFrame vigente, cualquier error requeriría volver a ejecutar todo el procesamiento anterior.
Un error común es pensar que al configurar inplace=True
ahorrará tiempo de procesamiento. Por lo general, esto no es exacto. Bajo el capó de Python, a menudo se crea y se trabaja en una copia de DataFrame, pero la copia reindexada se asigna a la variable del DataFrame original por usted.
Se recomienda no utilizar este parámetro ya que está programado para quedar obsoleto en una versión futura de Pandas. El motivo de la desaprobación es que configurar inplace
en True
cambia los datos subyacentes en su DataFrame original. Cualquier código que haga referencia a su DataFrame original desde cualquier otra parte de su programa hará referencia a los datos modificados, lo que puede introducir errores difíciles de encontrar.
Establecer inplace=True
también hace que el encadenamiento de métodos sea imposible. El encadenamiento de métodos es donde se aplican métodos sucesivos que cambian un DataFrame original, en lugar de crear muchos DataFrames intermedios mutantes. Pero el encadenamiento sólo funciona si los métodos utilizados en la cadena devuelven un DataFrame.
Si aplica un método DataFrame al resultado de reset_index()
cuando inplace
se ha establecido en True
, no se devolverá ningún DataFrame a aplíquelo y su código se romperá.
Ahora es el momento de que te diviertas un poco y pruebes el siguiente desafío:
Ya has visto cómo es posible restablecer un índice conservando el anterior. Cuando haces esto, pandas lo agrega como una nueva columna con el título index
. Eche un vistazo a la documentación de .reset_index()
y vea si puede descubrir cómo personalizar el nombre de esta nueva columna.
Ahora vuelva a leer los datos de band_members.csv
en un DataFrame nuevo y use beach_boys.index=range(1, 10)
para actualizar su índice. Finalmente, use .reset_index()
para ver si puede personalizar su DataFrame y hacer que se vea así:
>>> beach_boys
old_index first_name last_name instrument date_of_birth
0 1 Brian Wilson Bass 20-Jun-1942
1 2 Mike Love Saxophone 15-Mar-1941
2 3 Al Jardine Guitar 03-Sep-1942
3 4 Bruce Johnston Bass 27-Jun-1942
4 5 Carl Wilson Guitar 21-Dec-1946
5 6 Dennis Wilson Drums 04-Dec-1944
6 7 David Marks Guitar 22-Aug-1948
7 8 Ricky Fataar Drums 05-Sep-1952
8 9 Blondie Chaplin Guitar 07-Jul-1951
Su objetivo es asegurarse de que el índice existente no sólo se conserve, sino que también se le cambie el nombre.
Encontrará una solución en el cuaderno Solutions.ipynb
que se proporciona en los materiales descargables.
Aunque el método .reset_index()
que acaba de conocer es la forma más personalizable de restablecer un índice de Pandas DataFrame, lo que le permite manejar índices múltiples, ciertamente no es la única forma. Es posible hacerlo a la manera gremmie utilizando los primeros principios.
Restablecer un índice directamente con .index
Al trabajar con DataFrames, puede identificar filas usando .loc[]
o .iloc[]
. Cada uno tiene su caso de uso, aunque cualquiera puede usarse en cualquier DataFrame.
Se hace referencia al índice de un DataFrame mediante su propiedad .index
. Para reemplazar el índice actual con uno propio, asigna a .index
un iterable que contiene tus nuevas etiquetas de índice. Esto le permite muchas posibilidades para personalizar sus índices de DataFrame más allá de los números incrementales predeterminados.
Antes de explorar .loc[]
y .iloc[]
, agregará un índice personalizado a su DataFrame que contenga las iniciales de los miembros de la banda Beach Boys. Primero, leerás los datos de los miembros de la banda desde un archivo CSV y los convertirás a tipos de datos pyarrow
:
>>> beach_boys = pd.read_csv(
... "band_members.csv"
... ).convert_dtypes(dtype_backend="pyarrow")
>>> initials = ["BW", "ML", "AJ", "BJ", "CW", "DW", "DM", "RF", "BC"]
>>> beach_boys.index = initials
>>> beach_boys
first_name last_name instrument date_of_birth
BW Brian Wilson Bass 20-Jun-1942
ML Mike Love Saxophone 15-Mar-1941
AJ Al Jardine Guitar 03-Sep-1942
BJ Bruce Johnston Bass 27-Jun-1942
CW Carl Wilson Guitar 21-Dec-1946
DW Dennis Wilson Drums 04-Dec-1944
DM David Marks Guitar 22-Aug-1948
RF Ricky Fataar Drums 05-Sep-1952
BC Blondie Chaplin Guitar 07-Jul-1951
En breve veremos una forma alternativa de restablecer un índice, pero primero profundizaremos en la selección de filas.
Seleccione filas usando .loc[]
y .iloc[]
El atributo .loc[]
le permite indexar filas por su etiqueta de índice. Esto es particularmente útil cuando las etiquetas de índice subyacentes tienen un significado intrínseco dentro del DataFrame, como nombres de usuario o marcas de tiempo.
Si divide con .loc[]
, utiliza un intervalo cerrado, lo que significa que los valores de índice inicial y final que especifique aparecerán en la salida. Entonces, al seleccionar una porción de filas por nombre de usuario, su salida mostrará la primera, la última y todo lo demás.
El atributo .iloc[]
le permite buscar filas según su posición de índice, independientemente del valor de la etiqueta de índice. Cuando utiliza .iloc[]
, utiliza indexación de base cero. En otras palabras, la primera fila está en la ubicación 0
, no en 1
como cabría esperar. .iloc[]
utiliza un intervalo abierto, lo que significa que si bien el valor del índice inicial que especifique aparecerá en la salida, el final no.
Si bien estos conceptos le resultarán muy familiares si alguna vez ha dividido una cadena o una lista, es importante tener en cuenta que el elemento final .iloc[]
parece para seleccionar won. En realidad no será seleccionado.
Por supuesto, no importa si usa .iloc[]
o .loc[]
si está tratando con índices predeterminados porque estos también usan secuencias de base cero. , por lo que sus etiquetas y posiciones coinciden. Sin embargo, si su índice contiene cadenas o una secuencia numérica no predeterminada, los parámetros pasados a .iloc[]
no se parecerán al valor de índice real de la fila a la que está accediendo, lo que dificultará su código. para leer.
Nota: Si bien puede usar .iloc[]
y .loc[]
para seleccionar filas, generalmente es preferible usar . loc[]
si su índice tiene un significado explícito. De lo contrario, es posible que se sienta más cómodo usando .iloc[]
debido a su similitud con otras áreas de Python. Si utiliza índices predeterminados, no importará cuál elija.
Una buena forma de recordar la diferencia entre ellos es asociar mentalmente la letra inicial l de .loc[]
con la palabra label. Esto le recordará que .loc[]
utiliza valores de etiqueta de índice.
Ahora que su DataFrame se ha actualizado con un índice nuevo, puede usarlo para seleccionar algunas filas usando .loc[]
y .iloc[]
:
>>> beach_boys = pd.read_csv(
... "band_members.csv"
... ).convert_dtypes(dtype_backend="pyarrow")
>>> initials = ["BW", "ML", "AJ", "BJ", "CW", "DW", "DM", "RF", "BC"]
>>> beach_boys.index = initials
>>> beach_boys.loc[["BW"]]
first_name last_name instrument date_of_birth
BW Brian Wilson Bass 20-Jun-1942
>>> beach_boys.iloc[[1]]
first_name last_name instrument date_of_birth
ML Mike Love Saxophone 15-Mar-1941
>>> beach_boys.loc["BW":"BJ"]
first_name last_name instrument date_of_birth
BW Brian Wilson Bass 20-Jun-1942
ML Mike Love Saxophone 15-Mar-1941
AJ Al Jardine Guitar 03-Sep-1942
BJ Bruce Johnston Bass 27-Jun-1942
>>> beach_boys.iloc[1:4]
first_name last_name instrument date_of_birth
ML Mike Love Saxophone 15-Mar-1941
AJ Al Jardine Guitar 03-Sep-1942
BJ Bruce Johnston Bass 27-Jun-1942
En la línea 8, accedió a la primera fila cuyo valor de índice es BW
pasándolo como una cadena a .loc[]
. Al pasarlo como una lista a .loc[["BW"]]
, su salida se convierte en un DataFrame. Podrías haberlo pasado directamente, pero esto habría producido una serie de pandas que se comporta de manera diferente. El punto principal a tener en cuenta es que al pasar un valor de índice a .loc[]
, devuelve la fila cuya etiqueta de índice es ese valor.
Compare esto con el resultado después de la línea 12. El código accede a la fila número 1
, esta vez con .iloc[[1]]
. Observe cómo la salida es diferente. Usar .iloc[[1]]
significa que ha seleccionado la segunda fila del DataFrame. Recuerde, .iloc[]
trata la primera fila del DataFrame como 0
, independientemente de la etiqueta de índice real.
En la línea 16, seleccionó las primeras cuatro filas pasando las etiquetas de la primera y cuarta filas a .loc[]
.
Nota: Esta división devuelve los registros BW
y BJ
, además de todo lo intermedio, independientemente del orden alfabético. A veces es aconsejable ordenar un índice utilizando el método .sort_index()
del DataFrame antes de dividirlo si se requiere una selección alfabética de filas.
Finalmente, cuando pasó el segmento 1:4
a .iloc[]
en la línea 23, seleccionó las filas que comenzaban en la posición uno del índice; en otras palabras, la segunda fila. pero termina en la posición tres del índice. Nuevamente, esto se debe al efecto de numeración basada en cero de las filas y a que el último parámetro de segmento de la posición 4
está excluido. Recuerde que .iloc[]
asume un intervalo abierto.
Ahora es el momento de que pruebes otro desafío. Si te equivocas, siempre puedes Hacerlo de nuevo:
Una vez más, vuelva a leer los datos de band_members.csv
en un DataFrame nuevo. Ahora, vea si puede crear el DataFrame que se muestra a continuación asignando una lista apropiada a beach_boys.index
, luego seleccione las dos filas inferiores usando .loc[]
y .iloc[]
:
>>> beach_boys
first_name last_name instrument date_of_birth
2 Brian Wilson Bass 20-Jun-1942
4 Mike Love Saxophone 15-Mar-1941
6 Al Jardine Guitar 03-Sep-1942
8 Bruce Johnston Bass 27-Jun-1942
10 Carl Wilson Guitar 21-Dec-1946
12 Dennis Wilson Drums 04-Dec-1944
14 David Marks Guitar 22-Aug-1948
16 Ricky Fataar Drums 05-Sep-1952
18 Blondie Chaplin Guitar 07-Jul-1951
Esta vez, su índice contiene números pares que comienzan en 2
.
Encontrará una solución en el cuaderno Solutions.ipynb
que se proporciona en los materiales descargables.
Hasta ahora, ha utilizado .reset_index()
y .index
para restablecer un índice de DataFrame de pandas. Ahora es el momento de tallar y buscar otra alternativa.
Restablecer un índice directamente con .set_axis()
Una tercera forma de restablecer un índice es utilizar el método .set_axis()
del DataFrame. Este método le permite asignar un nuevo objeto RangeIndex
a su DataFrame y también le permite cambiar las etiquetas de las columnas.
Para alterar el índice existente de un DataFrame, puede pasar .set_axis()
un objeto range
utilizando el constructor integrado range()
. Esto asignará un intervalo de enteros ascendentes al índice que comienza en cero:
>>> beach_boys = pd.read_csv(
... "band_members.csv"
... ).convert_dtypes(dtype_backend="pyarrow")
>>> beach_boys.set_axis(range(len(beach_boys)))
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Al Jardine Guitar 03-Sep-1942
3 Bruce Johnston Bass 27-Jun-1942
4 Carl Wilson Guitar 21-Dec-1946
5 Dennis Wilson Drums 04-Dec-1944
6 David Marks Guitar 22-Aug-1948
7 Ricky Fataar Drums 05-Sep-1952
8 Blondie Chaplin Guitar 07-Jul-1951
Aquí, usó .set_axis()
para restablecer el índice a su valor predeterminado. Para hacer esto, pasó a .set_axis()
un range
cuya longitud era igual a la del DataFrame original beach_boys
. El uso de len()
garantiza que haya la cantidad correcta de números para cada fila en el DataFrame. Los números generados tendrán base cero y serán suficientes para cubrir cada fila. Como puede ver, el índice ahora se ha restablecido a su valor predeterminado.
Una vez más es hora de comprobar tu comprensión. No dudes en pedir ayuda a un amigo, pero solo si se llama Rhonda:
Vuelva a leer los datos de band_members.csv
. Ahora, use .set_axis()
para ver si puede hacer que se vea así:
>>> beach_boys
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
4 Al Jardine Guitar 03-Sep-1942
9 Bruce Johnston Bass 27-Jun-1942
16 Carl Wilson Guitar 21-Dec-1946
25 Dennis Wilson Drums 04-Dec-1944
36 David Marks Guitar 22-Aug-1948
49 Ricky Fataar Drums 05-Sep-1952
64 Blondie Chaplin Guitar 07-Jul-1951
Esta vez desea que cada valor del índice predeterminado se eleve al cuadrado.
Como de costumbre, encontrará una solución en el cuaderno Solutions.ipynb
que se proporciona en los materiales descargables.
Nota: En este punto, ha visto tres formas diferentes de restablecer un índice de DataFrame. Es posible que no sepa cuál de ellos debería utilizar. Si todo lo que desea hacer es restablecer su índice a su valor predeterminado, puede usar el módulo timeit para cronometrar pequeños fragmentos de código en IPython o Jupyter Notebook:
In [1]: import pandas as pd
In [2]: beach_boys = pd.read_csv(
...: "band_members.csv"
...: ).convert_dtypes(dtype_backend="pyarrow")
In [3]: %timeit -n 1000 beach_boys.reset_index(drop=True)
22.5 µs ± 1.71 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
In [4]: %timeit -n 1000 beach_boys.index = pd.RangeIndex(len(beach_boys.index))
3.75 µs ± 307 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
In [5]: %timeit -n 1000 beach_boys.set_axis(range(len(beach_boys)))
28.1 µs ± 1.89 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
Como puede ver en estos tres tiempos, si todo lo que necesita es restablecer un índice a su valor predeterminado, asignar un objeto RangeIndex
directamente a la propiedad .index
de su DataFrame es la forma más rápida. de los tres. También es la única forma de restablecer el índice en el DataFrame original. Las otras dos formas crean una copia que puedes asignar nuevamente a la variable beach_boys
. Sin embargo, .reset_index()
, aunque lento, ofrece más opciones de configuración.
Tenga en cuenta que las cifras de tiempo exactas serán diferentes de las que se muestran aquí, pero deberían mostrar la misma tendencia.
Ahora que sabes cómo restablecer el índice de un DataFrame, continuarás y aprenderás por qué querrías hacer esto. Todavía no es momento de relajarse.
Restaurar un índice secuencial
Cuando limpia datos antes del análisis, a menudo necesita eliminar ciertas filas de un DataFrame. Por ejemplo, es posible que deba eliminar filas duplicadas u otras filas no deseadas. Cuando los elimina, los valores de índice de las filas también se eliminan. Esto podría dar lugar a que aparezcan lagunas en el índice. Al restablecer el índice, puede solucionar este problema.
Más adelante, en la sección sobre cómo alinear índices de varios DataFrames, aprenderá cómo los valores faltantes en el índice de un DataFrame pueden causar estragos cuando necesita analizar sus datos. Por ahora, arruinarás el índice de tu encantador DataFrame beach_boys
:
>>> beach_boys = pd.read_csv(
... "band_members.csv"
... ).convert_dtypes(dtype_backend="pyarrow")
>>> beach_boys
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Al Jardine Guitar 03-Sep-1942
3 Bruce Johnston Bass 27-Jun-1942
4 Carl Wilson Guitar 21-Dec-1946
5 Dennis Wilson Drums 04-Dec-1944
6 David Marks Guitar 22-Aug-1948
7 Ricky Fataar Drums 05-Sep-1952
8 Blondie Chaplin Guitar 07-Jul-1951
>>> beach_boys.drop(labels=[3, 5])
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Al Jardine Guitar 03-Sep-1942
4 Carl Wilson Guitar 21-Dec-1946
6 David Marks Guitar 22-Aug-1948
7 Ricky Fataar Drums 05-Sep-1952
8 Blondie Chaplin Guitar 07-Jul-1951
Como puede ver, el DataFrame contiene las nueve filas originales de miembros de la banda con un índice predeterminado. Para eliminar algunas filas, utilizó el método .drop()
del DataFrame. Las filas que se eliminarán se definieron en la lista de Python proporcionada a su parámetro labels
. En este caso, se eliminaron las filas cuya etiqueta de índice es 3
o 5
. Mire detenidamente el índice en el resultado generado debajo de la línea 17 y verá que el índice ya no es secuencial.
Para solucionar este problema, puedes utilizar cualquiera de las técnicas que has aprendido hasta ahora. Aquí, usarás .reset_index()
que, debido a que no cambia el DataFrame subyacente, significa que puedes reutilizar el DataFrame original indexado limpiamente en ejemplos posteriores:
>>> (
... beach_boys
... .drop(labels=[3, 5])
... .reset_index()
... )
index first_name last_name instrument date_of_birth
0 0 Brian Wilson Bass 20-Jun-1942
1 1 Mike Love Saxophone 15-Mar-1941
2 2 Al Jardine Guitar 03-Sep-1942
3 4 Carl Wilson Guitar 21-Dec-1946
4 6 David Marks Guitar 22-Aug-1948
5 7 Ricky Fataar Drums 05-Sep-1952
6 8 Blondie Chaplin Guitar 07-Jul-1951
Como vio anteriormente, .reset_index()
ha agregado un nuevo índice predeterminado a su DataFrame. Sin embargo, todavía no está satisfecho porque su índice original aún permanece, aunque en una nueva columna. Una vez más, necesita ajustar el parámetro drop
de .reset_index()
para completar el trabajo:
>>> (
... beach_boys
... .drop(labels=[3, 5])
... .reset_index(drop=True)
... )
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Al Jardine Guitar 03-Sep-1942
3 Carl Wilson Guitar 21-Dec-1946
4 David Marks Guitar 22-Aug-1948
5 Ricky Fataar Drums 05-Sep-1952
6 Blondie Chaplin Guitar 07-Jul-1951
Como puede ver, al configurar drop=True
, el índice original ahora no se ve por ninguna parte, pero el nuevo y brillante se ve, bueno, nuevo y brillante.
Una vez más, es hora de comprobar su comprensión. Ah, y si no puedes resolverlo, No te preocupes, bebé:
Para comenzar, vuelva a leer los datos de band_members.csv
, luego use beach_boys.drop(labels=[3, 5])
para eliminar algunas de las filas. Acabas de aprender cómo restablecer el índice a su valor predeterminado usando .reset_index(drop=True)
. Vea si puede hacer esto nuevamente usando cualquiera de las otras dos técnicas que ha aprendido. Tu respuesta debería verse así:
>>> beach_boys
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Al Jardine Guitar 03-Sep-1942
3 Carl Wilson Guitar 21-Dec-1946
4 David Marks Guitar 22-Aug-1948
5 Ricky Fataar Drums 05-Sep-1952
6 Blondie Chaplin Guitar 07-Jul-1951
Como puede ver, el índice predeterminado ha sido restaurado y el original no se encuentra por ninguna parte.
Al igual que con los otros ejercicios, encontrará una solución en el cuaderno Solutions.ipynb
que se proporciona en los materiales descargables.
Todos tus esfuerzos hasta ahora pueden significar que ahora estás viendo una aleta gemela. A continuación, volverá a su tablero y se deshará de esos duplicados.
Eliminar valores de índice duplicados
Quizás le sorprenda saber que los índices a veces pueden tener valores duplicados. No es necesario que sean identificadores únicos. Sin embargo, los duplicados suelen ser algo que conviene evitar porque pueden causar problemas. Afortunadamente, .reset_index()
puede encargarse de esto por usted.
Los valores de índice duplicados a menudo surgen cuando se fusionan dos DataFrames. La duplicación puede causar problemas con la selección, el corte y el filtrado de filas incorrectos. Antes de que pueda ver estos problemas, primero debe aplicar algunos valores duplicados a su índice:
>>> beach_boys = pd.read_csv(
... "band_members.csv"
... ).convert_dtypes(dtype_backend="pyarrow")
>>> guitar_players = beach_boys.query(
... "instrument == 'Guitar'"
... ).reset_index(drop=True)
>>> guitar_players
first_name last_name instrument date_of_birth
0 Al Jardine Guitar 03-Sep-1942
1 Carl Wilson Guitar 21-Dec-1946
2 David Marks Guitar 22-Aug-1948
3 Blondie Chaplin Guitar 07-Jul-1951
>>> others = beach_boys.query(
... "instrument != 'Guitar'"
... ).reset_index(drop=True)
>>> others
first_name last_name instrument date_of_birth
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Bruce Johnston Bass 27-Jun-1942
3 Dennis Wilson Drums 04-Dec-1944
4 Ricky Fataar Drums 05-Sep-1952
Aquí, ha dividido el DataFrame original en dos nuevos. El DataFrame guitar_players
, que se muestra debajo de la línea 9, contiene los registros de los miembros del grupo que tocan la guitarra. El marco de datos others
, que se muestra debajo de la línea 20, contiene el resto de los miembros.
Para seleccionar a los guitarristas, pasó la cadena de consulta "instrument == 'Guitar'"
a .query()
en las líneas 5 a 7, lo que extrae todas las filas donde Los valores de la columna instrumento
coinciden con "Guitarra"
.
Las líneas 16 a 18 usan un código similar que crea un segundo DataFrame que contiene las otras filas. En este caso, músicos que no están marcados como guitarristas.
En ambos casos, se utilizó .reset_index()
para garantizar que el índice en ambos DataFrames nuevos fuera secuencial. Esto aseguró que algunos valores de índice idénticos aparecieran en ambos DataFrames. Cuando fusiones ambos, podrías pensar que volverás a tu DataFrame original, pero no lo harás:
>>> all_beach_boys = pd.concat([guitar_players, others])
>>> all_beach_boys
first_name last_name instrument date_of_birth
0 Al Jardine Guitar 03-Sep-1942
1 Carl Wilson Guitar 21-Dec-1946
2 David Marks Guitar 22-Aug-1948
3 Blondie Chaplin Guitar 07-Jul-1951
0 Brian Wilson Bass 20-Jun-1942
1 Mike Love Saxophone 15-Mar-1941
2 Bruce Johnston Bass 27-Jun-1942
3 Dennis Wilson Drums 04-Dec-1944
4 Ricky Fataar Drums 05-Sep-1952
Ha creado un único DataFrame nuevo usando concat()
. Al pasarlo tanto a guitar_players
como a others
, su nuevo DataFrame all_beach_boys
muestra a los nueve miembros originales de la banda una vez más, pero el índice contiene duplicados. Ahora que tiene un DataFrame con índices duplicados, investigará los problemas que esto puede causar.
Supongamos que desea seleccionar la cuarta fila: la fila cuya posición de índice es 3
. No puedes usar .loc[]
para hacer esto porque el índice duplicado causa problemas. Ejecute el siguiente código y verá el problema:
>>> all_beach_boys.loc[3]
first_name last_name instrument date_of_birth
3 Blondie Chaplin Guitar 07-Jul-1951
3 Dennis Wilson Drums 04-Dec-1944
>>> all_beach_boys.iloc[[3]]
first_name last_name instrument date_of_birth
3 Blondie Chaplin Guitar 07-Jul-1951
Eche un vistazo a las líneas resaltadas. Como puede ver, debido a que .loc[]
seleccionó filas cuya etiqueta de índice es 3
, se devolvieron dos registros. Para solucionar este problema, deberá utilizar .iloc[]
para seleccionar la fila única requerida.
Los valores de índice duplicados también causan estragos cuando intenta seleccionar filas contiguas mediante el corte. Supongamos que desea ver las filas en las posiciones de índice tres y cuatro. Su primer intento podría ser probar .loc[]
:
>>> all_beach_boys.loc[3:4]
Traceback (most recent call last):
...
KeyError: 'Cannot get left slice bound for non-unique label: 3'
>>> all_beach_boys.iloc[3:5]
first_name last_name instrument date_of_birth
3 Blondie Chaplin Guitar 07-Jul-1951
0 Brian Wilson Bass 20-Jun-1942
Como puede ver, cuando intenta pasar las posiciones de índice requeridas a .loc[]
, genera una excepción KeyError
porque tiene una etiqueta no única. Para solucionar este problema, deberá recurrir al uso de .iloc[]
en su lugar.
Nota: Es posible utilizar el corte con .loc[]
cuando se trata de índices duplicados. Antes de hacer esto, asegúrese de ordenar el índice primero usando .sort_index()
. De lo contrario, generará una excepción KeyError
debido a los valores duplicados:
>>> all_beach_boys.sort_index().loc[3:4]
first_name last_name instrument date_of_birth
3 Blondie Chaplin Guitar 07-Jul-1951
3 Dennis Wilson Drums 04-Dec-1944
4 Ricky Fataar Drums 05-Sep-1952
Como puede ver, se han devuelto las filas con etiquetas de índice 3
y 4
.
Supongamos que ahora desea ver esos elementos con etiquetas de índice 1
y 3
. Esta vez, utiliza el método .filter()
del DataFrame:
>>> all_beach_boys.filter(items=[1, 3], axis="index")
Traceback (most recent call last):
...
ValueError: cannot reindex on an axis with duplicate labels
Ha intentado filtrar el DataFrame con etiquetas de índice 1
y 3
pasándolas como una lista al parámetro items
de .filtro()
. También configuró el parámetro axis
en "index"
para aplicar el filtro al índice. A pesar de que su código es técnicamente correcto, el resultado es una excepción ValueError
debido a las etiquetas duplicadas.
En este momento, probablemente te sientas un poco muñecado con todos estos contratiempos. Es hora de volver a subirte a tu tablero y resolver los problemas:
Vea si puede corregir este código para que tanto .loc[]
como .iloc[]
produzcan los mismos resultados, y así .filter()
funciona como se esperaba cuando se aplica a all_beach_boys
. Además, asegúrese de que se haya eliminado el índice antiguo problemático:
>>> all_beach_boys.loc[[3]]
first_name last_name instrument date_of_birth
3 Blondie Chaplin Guitar 07-Jul-1951
>>> all_beach_boys.iloc[[3]]
first_name last_name instrument date_of_birth
3 Blondie Chaplin Guitar 07-Jul-1951
>>> all_beach_boys.filter(items=[1, 3], axis="index")
first_name last_name instrument date_of_birth
1 Carl Wilson Guitar 21-Dec-1946
3 Blondie Chaplin Guitar 07-Jul-1951
Bien hecho. ¡Todo funciona!
Ahora supongamos que desea promover una columna existente a un índice. ¿Es esto posible? Es hora de dejar caer, coger una ola y ver.
Utilice una columna existente como índice
Si bien el índice numérico secuencial predeterminado proporciona un acceso único a las filas dentro de su DataFrame, es poco probable que tenga algún significado inherente. Por ejemplo, los números asignados a cada fila de los DataFrames que ha utilizado hasta este momento no tienen significado en relación con los datos que están indexando.
En el DataFrame leído desde band_members.csv
, el miembro de la banda Brian Wilson
tiene un valor de índice de 0
simplemente porque aparece primero en el archivo. Esto no tiene ningún significado inherente, aunque puede ofenderte si eres un fan y crees que él debería ser el número 1
.
Si bien el concepto de utilizar un índice secuencial no relacionado le resultará familiar si ha trabajado con claves en una base de datos relacional, es posible que desee algo más significativo en sus DataFrames.
Si desea etiquetas de índice más fáciles de usar, puede utilizar una columna existente y promoverla en el índice. Para hacer esto, utiliza el método .set_index()
. Aunque puede promocionar cualquier columna existente para que se convierta en índice, tenga en cuenta que, a menos que la columna deseada contenga valores únicos, seguirá teniendo los mismos problemas con los duplicados que vio anteriormente.
Supongamos que desea restablecer su índice para que contenga las etiquetas first_name
. Podrías hacer esto como se muestra aquí:
>>> beach_boys = pd.read_csv(
... "band_members.csv"
... ).convert_dtypes(dtype_backend="pyarrow")
>>> (
... beach_boys
... .set_index("first_name")
... .loc[["Brian", "Carl"]]
... )
last_name instrument date_of_birth
first_name
Brian Wilson Bass 20-Jun-1942
Carl Wilson Guitar 21-Dec-1946
Cuando llamas a .set_index()
en beach_boys
y pasas "first_name"
, esta columna se promueve al índice. Luego puedes usar .loc[]
para seleccionar una o más filas usando los nombres de los músicos que te interesan.
En algunos casos, es posible que desee restablecer su índice para que sus valores existentes sean más significativos para los datos que están indexando. Si bien no puedes usar .reset_index()
para esto, puedes aplicar algo más adecuado al atributo .index
del DataFrame.
Un ejemplo común es el uso de identificadores de empleados en lugar de números enteros secuenciales simples. El siguiente código actualiza el índice secuencial existente con más valores contextuales:
>>> beach_boys.index = [f"Employee_{x + 1}" for x in range(len(beach_boys))]
>>> beach_boys
first_name last_name instrument date_of_birth
Employee_1 Brian Wilson Bass 20-Jun-1942
Employee_2 Mike Love Saxophone 15-Mar-1941
Employee_3 Al Jardine Guitar 03-Sep-1942
Employee_4 Bruce Johnston Bass 27-Jun-1942
Employee_5 Carl Wilson Guitar 21-Dec-1946
Employee_6 Dennis Wilson Drums 04-Dec-1944
Employee_7 David Marks Guitar 22-Aug-1948
Employee_8 Ricky Fataar Drums 05-Sep-1952
Employee_9 Blondie Chaplin Guitar 07-Jul-1951
En este código, utilizó una lista por comprensión para crear una lista de cadenas que contienen ["Employee_1", "Employee_2", ...]
. Luego, esto se asigna al atributo .index
de beach_boys
.
Ahora que tiene un índice más significativo, puede usarlo de la misma manera que usó el índice numérico predeterminado. Por ejemplo, puede seleccionar filas por sus nuevos valores Employee_
:
>>> beach_boys.loc[["Employee_4"]]
first_name last_name instrument date_of_birth
Employee_4 Bruce Johnston Bass 27-Jun-1942
En el código anterior, utilizó .loc[]
para seleccionar el registro de Employee_4
.
Ahora un poco de alucinación. ¿No sería bueno si pudieras hacer esto?
Utilizando el marco de datos beach_boys
original leído desde band_members.csv
, cree un índice que consta de los nombres de usuario del personal en el formato
. Su resultado final debería verse así:
>>> beach_boys
first_name last_name instrument date_of_birth
WilsonB Brian Wilson Bass 20-Jun-1942
LoveM Mike Love Saxophone 15-Mar-1941
JardineA Al Jardine Guitar 03-Sep-1942
JohnstonB Bruce Johnston Bass 27-Jun-1942
WilsonC Carl Wilson Guitar 21-Dec-1946
WilsonD Dennis Wilson Drums 04-Dec-1944
MarksD David Marks Guitar 22-Aug-1948
FataarR Ricky Fataar Drums 05-Sep-1952
ChaplinB Blondie Chaplin Guitar 07-Jul-1951
Como puede ver, el índice ahora contiene un formato de nombre de usuario común, lo que facilitará la selección de usuarios por sus nombres de usuario.
A continuación, adquirirás algo de experiencia surf en tándem. Es hora de utilizar no uno, sino dos DataFrames juntos.
Alinear índices de varios marcos de datos
Una de las grandes características de trabajar con pandas DataFrames es que puede utilizar los operadores aritméticos básicos para sumar sus datos. Desafortunadamente, sólo se le permitirá esta comodidad si sus índices se alinean. De lo contrario, tendrá problemas.
Suponga que está analizando las ventas semanales de discos de una tienda de discos. Los datos de ventas de dos semanas se almacenan dentro de dos archivos CSV denominados week1_record_sales.csv
y week2_record_sales.csv
. A modo de demostración, ambos archivos contienen datos de ventas idénticos pero sus índices son diferentes:
>>> week1_sales = pd.read_csv(
... "week1_record_sales.csv"
... ).set_index("index")
>>> week2_sales = pd.read_csv(
... "week2_record_sales.csv"
... ).set_index("index")
>>> week1_sales
day sales
index
0 Mon 100
1 Tue 150
2 Wed 200
3 Thu 250
4 Fri 300
>>> week2_sales
day sales
index
1 Mon 100
2 Tue 150
3 Wed 200
4 Thu 250
5 Fri 300
Cada archivo se lee en un DataFrame y contiene información de ventas diarias. Cada fila se identifica por su columna index
, que se ha establecido como índice del DataFrame con .set_index()
.
Suponga que ahora desea encontrar las ventas totales de ambas semanas. Esto debería poder lograrse con poco más que una simple operación aritmética:
>>> week1_sales["sales"] + week2_sales["sales"]
index
0 NaN
1 250.0
2 350.0
3 450.0
4 550.0
5 NaN
Name: sales, dtype: float64
Como puedes ver, algo salió mal. Debido a que ambos DataFrames contienen los mismos datos, es de esperar que las respuestas sean el doble de sus valores originales. En cambio, la primera y la última respuesta son NaN
, lo que significa que no se pudo realizar un cálculo aritmético debido a valores faltantes. Además, los resultados restantes son incorrectos.
Ambos problemas fueron causados por índices no coincidentes. Los valores NaN
han aparecido porque ni el índice 0
ni el índice 5
aparecen en ambos DataFrames. Los cálculos son incorrectos porque, por ejemplo, la cifra de ventas del miércoles de 200
está indexada como 2
en su primer DataFrame, mientras que el índice 2
se refiere a las ventas del martes de 150
en su segundo DataFrame. Cuando los agregas, el resultado no tiene sentido.
También puede fusionar dos DataFrames de la misma manera que se pueden fusionar tablas de bases de datos relacionales. Esto le permite ver datos coincidentes de ambos DataFrames en el mismo lugar. Nuevamente, si se une a un índice, cada valor de índice debe hacer referencia a los datos relacionados en ambos DataFrames.
Por ejemplo, supongamos que desea ver todos los datos de ambas semanas de ventas. Para hacer esto, puede usar el método .merge()
del DataFrame:
>>> week1_sales.merge(week2_sales, left_index=True, right_index=True)
day_x sales_x day_y sales_y
index
1 Tue 150 Mon 100
2 Wed 200 Tue 150
3 Thu 250 Wed 200
4 Fri 300 Thu 250
Inmediatamente puedes ver algunos problemas. Ni los registros con índice 0
ni el índice 5
se ven por ningún lado. Las cifras diarias tampoco coinciden.
Aquí, ha realizado una unión interna de ambos DataFrames, lo que significa que solo se fusionarán los registros cuyos valores de índice aparezcan en ambos DataFrames. Debido a que los valores de índice 0
y 5
no aparecen en ambos, no se incluyen en la combinación. Los días no coinciden porque el mismo índice hace referencia a días diferentes en cada DataFrame.
Para solucionar ambos problemas, debe asegurarse de que ambos DataFrames estén usando el mismo índice. Una forma sería restablecer el índice de week2_sales
a su valor predeterminado. Esto coincidirá con el usado por week1_sales
, pero solo porque los datos diarios para ambos DataFrames ya están en el mismo orden:
>>> week2_sales = week2_sales.reset_index(drop=True)
Como antes, para restablecer el índice a su valor predeterminado, use .reset_index()
y pase True
a su parámetro drop
para eliminar el problema. índice original. Ahora, cuando ejecutas los dos fragmentos de código anteriores, los resultados son mucho más aceptables:
>>> week1_sales["sales"] + week2_sales["sales"]
index
0 200
1 300
2 400
3 500
4 600
Name: sales, dtype: int64
>>> week1_sales.merge(week2_sales, left_index=True, right_index=True)
day_x sales_x day_y sales_y
index
0 Mon 100 Mon 100
1 Tue 150 Tue 150
2 Wed 200 Wed 200
3 Thu 250 Thu 250
4 Fri 300 Fri 300
Como puedes ver, ahora todo coincide y no falta nada. Alinear los índices ha resuelto ambos problemas de una sola vez. Sin embargo, este ejemplo solo funcionó porque, para empezar, las filas dentro de los DataFrames estaban en el orden correcto. Este no será siempre el caso.
Esta vez vas a pensar lateralmente. Así que dale a tu cerebro un Wipeout y mira si puedes resolver este ejercicio:
Supongamos que está satisfecho con el índice de week2_sales
, pero no con el del week1_sales
DataFrame. Vea si puede utilizar una de las técnicas que aprendió anteriormente para aplicar el índice de week2_sales
al de week1_sales
. No olvide asegurarse de que tanto la adición como .merge()
sigan produciendo el resultado correcto.
Hasta ahora, ha fusionado los DataFrames en índices numéricos. ¿Se te ocurre una alternativa mejor que funcione incluso si ambos DataFrames originales tuvieran sus filas en un orden diferente? Nuevamente, asegúrese de que tanto la suma como .merge()
produzcan el resultado correcto.
Recuerde, siempre puede echar un vistazo a la solución en los materiales descargados.
Para completar su experiencia de aprendizaje, terminará aprendiendo cómo restablecer índices multinivel en DataFrames. No es algo que los surfistas hagan normalmente, a menos que sean Pythonistas como tú.
Restablecer índices múltiples
Cada uno de los DataFrames con los que ha estado trabajando hasta ahora consta de objetos Index
de una sola columna. Los DataFrames también admiten objetos MultiIndex
, que proporcionan índices jerárquicos o de varios niveles para sus DataFrames.
En esta sección, empiezas a despertarte de tu California Dreaming con los Beach Boys y decides desayunar. Utilizarás el archivo cereals.csv
para ayudarte a decidir qué cereal comer. Este archivo contiene datos sobre varios cereales para el desayuno populares de una variedad de fabricantes. Los datos originales provienen de Kaggle y están disponibles gratuitamente bajo la licencia Creative Commons. Aquí, estás usando una versión reducida.
Lo primero que deberá hacer es leer los datos de los cereales en un DataFrame:
>>> cereals = pd.read_csv("cereals.csv").convert_dtypes(
... dtype_backend="pyarrow"
... )
>>> cereals.head()
name manufacturer type fiber
0 100% Bran Nabisco Cold 10.0
1 100% Natural Bran Quaker Oats Cold 2.0
2 All-Bran Kelloggs Cold 9.0
3 All-Bran with Extra Fiber Kelloggs Cold 14.0
4 Almond Delight Ralston Purina Cold 1.0
Como puedes ver, el archivo contiene detalles de diferentes cereales para el desayuno. Cuando llamas al método .head()
del DataFrame, ves los primeros cinco registros que revelan el nombre
y el fabricante
del cereal. También podrás ver su tipo
, que te indica si el cereal se debe consumir frío o caliente, así como su contenido en fibra
.
No es sorprendente que este DataFrame tenga un índice simple. Una forma rápida de crear un MultiIndex
es crear una tabla dinámica a partir de él:
>>> cereals.pivot_table(
... values="fiber",
... index=["manufacturer", "type"],
... aggfunc="mean",
... )
fiber
manufacturer type
American Home Food Products Hot 0.0
General Mills Cold 1.272727
Kelloggs Cold 2.73913
Nabisco Cold 4.6
Hot 1.0
Post Cold 2.777778
Quaker Oats Cold 1.142857
Hot 2.7
Ralston Purina Cold 1.875
Esta tabla dinámica, que en realidad es otro DataFrame, analiza los datos sin procesar calculando el contenido promedio de fibra para cada tipo de cereal para cada fabricante. El índice de este DataFrame es un poco diferente de lo que estás acostumbrado a ver:
>>> cereals.pivot_table(
... values="fiber",
... index=["manufacturer", "type"],
... aggfunc="mean",
... ).index
MultiIndex([('American Home Food Products', 'Hot'),
( 'General Mills', 'Cold'),
( 'Kelloggs', 'Cold'),
( 'Nabisco', 'Cold'),
( 'Nabisco', 'Hot'),
( 'Post', 'Cold'),
( 'Quaker Oats', 'Cold'),
( 'Quaker Oats', 'Hot'),
( 'Ralston Purina', 'Cold')],
names=['manufacturer', 'type'])
El MultiIndex
en esta tabla dinámica consta de columnas fabricante
y tipo
. En lugar de las simples columnas individuales que ha visto hasta ahora, ahora tiene una estructura de varios niveles más compleja.
En este ejemplo, ha creado un MultiIndex
que consta de dos niveles. Estos se definen pasando "manufacturer"
y "type"
al parámetro index
de .pivot_table()
.
Dentro del objeto MultiIndex
, fabricante
se conoce como nivel 0, mientras que tipo
es nivel 1 . . Estos números de nivel son importantes si necesita restablecer el índice porque le permiten hacerlo en un nivel específico, o incluso restablecerlo por completo.
Supongamos que desea restablecer solo el nivel 1, correspondiente a type
, lo que lo relega a una columna separada antes de eliminarlo por completo:
>>> cereals = pd.read_csv("cereals.csv").convert_dtypes(dtype_backend="pyarrow")
>>> cereals.pivot_table(
... values="fiber",
... index=["manufacturer", "type"],
... aggfunc="mean"
... ).reset_index(level=1, drop=True)
>>> cereals
fiber
manufacturer
American Home Food Products 0.0
General Mills 1.272727
Kelloggs 2.73913
Nabisco 4.6
Nabisco 1.0
Post 2.777778
Quaker Oats 1.142857
Quaker Oats 2.7
Ralston Purina 1.875
Al pasar level=1
y drop=True
a .reset_index()
, eliminas los detalles de type
, conservando sólo la información del fabricante
como un simple Índice
.
Tenga cuidado al hacer esto, porque ahora ha creado valores de índice duplicados con todos los problemas que vio anteriormente. Además, sus datos ahora han perdido parte de su significado. Por ejemplo, existe confusión sobre lo que le muestran las etiquetas Nabisco
y Quaker Oats
. Ya no sabes cuál se refiere a los cereales calientes y cuál a los fríos.
Tenga en cuenta que restablecer parte de un MultiIndex
puede tener efectos secundarios indeseables que no siempre son obvios.
Es hora de Coger una ola y realizar un Surfin’ Safari en tu penúltimo desafío:
Usando el código anterior como guía, vea si puede producir este resultado exacto para aclarar la confusión de Nabisco
y Quaker Oats
:
>>> cereals
manufacturer fiber
type
Cold General Mills 1.272727
Cold Kelloggs 2.73913
Cold Nabisco 4.6
Cold Post 2.777778
Cold Quaker Oats 1.142857
Cold Ralston Purina 1.875
Hot American Home Food Products 0.0
Hot Nabisco 1.0
Hot Quaker Oats 2.7
La información de tipo
forma el índice, mientras que la información de fabricante
está nuevamente en una columna.
A veces, es mejor restablecer todos los niveles de un MultiIndex
pero conservar todos los datos. Cuando aplica .reset_index()
a un MultiIndex
usando sus parámetros predeterminados, reemplazará el índice completo con una versión predeterminada simple y creará columnas adicionales a partir del índice original dentro. su marco de datos:
>>> cereals.pivot_table(
... values="fiber",
... index=["manufacturer", "type"],
... aggfunc="mean",
... ).reset_index()
manufacturer type fiber
0 American Home Food Products Hot 0.0
1 General Mills Cold 1.272727
2 Kelloggs Cold 2.73913
3 Nabisco Cold 4.6
4 Nabisco Hot 1.0
5 Post Cold 2.777778
6 Quaker Oats Cold 1.142857
7 Quaker Oats Hot 2.7
8 Ralston Purina Cold 1.875
Esta vez, su DataFrame tiene un índice predeterminado aplicado, pero también tiene nuevas columnas manufacturer
y type
, así como la columna agregada fiber
. datos. Lo más importante es que los datos no han perdido nada de su significado.
Este desafío final pondrá a prueba esas buenas vibraciones que ahora tienes sobre tu capacidad para trabajar con índices de DataFrame.
Vea si puede resolver los efectos secundarios indeseables de su tabla dinámica original aplanando el MultiIndex
. Quizás se vea así:
>>> cereals
fiber
(American Home Food Products, Hot) 0.0
(General Mills, Cold) 1.272727
(Kelloggs, Cold) 2.73913
(Nabisco, Cold) 4.6
(Nabisco, Hot) 1.0
(Post, Cold) 2.777778
(Quaker Oats, Cold) 1.142857
(Quaker Oats, Hot) 2.7
(Ralston Purina, Cold) 1.875
El índice ahora consta de un nivel en lugar de dos, pero cada nivel es una tupla.
¡Eso es todo! Debería estar emocionado de saber que ahora tiene un conocimiento completo de cómo restablecer el índice en sus DataFrames utilizando varias técnicas. También recibió una lección adicional sobre cómo incorporar títulos de canciones de Beach Boys y referencias cursis de navegación en un tutorial de Python. Un original verdaderamente rad de tus amigos de Real Python.
Conclusión
En este tutorial, aprendió que si bien el método .reset_index()
es la forma más personalizable de restablecer un índice, no es la opción más rápida. Sin embargo, es útil cuando trabaja con restablecimientos de MultiIndex
.
También aprendió que aplicar directamente el índice a la propiedad .index
del DataFrame es la forma más rápida de restablecer un índice y que cambia el DataFrame original en el proceso. Además, descubrió cómo el método .set_axis()
le permite restablecer y volver a etiquetar su índice si así lo desea.
Felicitaciones por completar este tutorial y disfrute aplicando estas nuevas habilidades para preparar mejor sus DataFrames para el análisis. ¡Feliz surf!