Python con Pandas: tutorial de DataFrame con ejemplos

En este artículo, explicaremos qué son los Pandas DataFrames y cómo almacenan información. Luego, los crearemos manualmente y a partir de archivos, así como también manipularemos los datos almacenados dentro de ellos.

Introducción

Pandas es una biblioteca Python de código abierto para el análisis de datos. Está diseñado para el manejo y procesamiento eficiente e intuitivo de datos estructurados.

Las dos estructuras de datos principales en Pandas son Series y DataFrame. Las ‘series’ son esencialmente matrices etiquetadas unidimensionales de cualquier tipo de datos, mientras que los ‘DataFrame’ son bidimensionales, con tipos de datos potencialmente heterogéneos, matrices etiquetadas de cualquier tipo de datos. Heterogéneo significa que no todas las "filas" deben tener el mismo tamaño.

En este artículo, veremos las formas más comunes de crear un DataFrame y los métodos para cambiar su estructura.

Usaremos el Jupyter Notebook ya que ofrece una buena representación visual de DataFrames. Sin embargo, cualquier IDE también hará el trabajo, simplemente llamando a una instrucción print() en el objeto DataFrame.

Creación de tramas de datos {#creación de tramas de datos}

Cada vez que crea un DataFrame, ya sea que esté creando uno manualmente o generando uno a partir de una fuente de datos como un archivo, los datos tienen que ordenarse de forma tabular, como una secuencia de filas que contienen datos.

Esto implica que las filas comparten el mismo orden de campos, es decir, si desea tener un ‘DataFrame’ con información sobre el nombre y la edad de una persona, debe asegurarse de que todas sus filas contengan la información de la misma manera. .

Cualquier discrepancia hará que el DataFrame sea defectuoso, lo que generará errores.

Creación de un marco de datos vacío

Crear un DataFrame vacío es tan simple como:

1
2
import pandas as pd
dataFrame1 = pd.DataFrame()

Echaremos un vistazo a cómo puede agregar filas y columnas a este DataFrame vacío mientras manipula su estructura.

Creación de un marco de datos a partir de listas

Siguiendo el principio de "secuencia de filas con el mismo orden de campos", puede crear un DataFrame a partir de una lista que contenga dicha secuencia, o a partir de múltiples listas zip()-combinadas de tal manera que proporcionan una secuencia como esa:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd

listPepper = [ 
            [50, "Bell pepper", "Not even spicy"], 
            [5000, "Espelette pepper", "Uncomfortable"], 
            [500000, "Chocolate habanero", "Practically ate pepper spray"]
            ]

dataFrame1 = pd.DataFrame(listPepper)

dataFrame1
# If you aren't using Jupyter, you'll have to call `print()`
# print(dataFrame1) 

Esto resulta en:

dataframe results

Se podría haber logrado el mismo efecto al tener los datos en varias listas y ‘comprimirlos ()’ juntos. Este enfoque se puede usar cuando los datos que tenemos se proporcionan con listas de valores para una sola columna (campo), en lugar de la forma antes mencionada en la que una lista contiene datos para cada fila en particular como una unidad.

Lo que significa que tenemos todos los datos (en orden) para las columnas individualmente, que, cuando se comprimen juntas, crean filas.

Es posible que haya notado que las etiquetas de columna y fila no son muy informativas en el DataFrame que hemos creado. Puede pasar información adicional al crear el DataFrame, y una cosa que puede hacer es dar las etiquetas de fila/columna que desea usar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import pandas as pd

listScoville = [50, 5000, 500000]
listName = ["Bell pepper", "Espelette pepper", "Chocolate habanero"]
listFeeling = ["Not even spicy", "Uncomfortable", "Practically ate pepper spray"]

dataFrame1 = pd.DataFrame(zip(listScoville, listName, listFeeling), columns = ['Scoville', 'Name', 'Feeling'])

# Print the dataframe
dataFrame1

Lo que nos daría el mismo resultado que antes, solo que con nombres de columna más significativos:

changing column names in a dataframe

Otra representación de datos que puede usar aquí es proporcionar los datos como una lista de diccionarios en el siguiente formato:

1
2
3
4
5
listPepper = [
    { columnName1 : valueForRow1, columnName2: valueForRow1, ... },
    { columnName1 : valueForRow2, columnName2: valueForRow2, ... },
    ...
]

En nuestro ejemplo, la representación se vería así:

1
2
3
4
5
listPepper = [
  {'Scoville' : 50, 'Name' : 'Bell pepper', 'Feeling' : 'Not even spicy'},
  {'Scoville' : 5000, 'Name' : 'Espelette pepper', 'Feeling' : 'Uncomfortable'},
  {'Scoville' : 500000, 'Name' : 'Chocolate habanero', 'Feeling' : 'Practically ate pepper spray'},
]

Y crearíamos el DataFrame de la misma forma que antes:

1
dataFrame1 = pd.DataFrame(listPepper)

Crear un marco de datos a partir de diccionarios

Los diccionarios son otra forma de proporcionar datos en forma de columnas. A cada columna se le da una lista de valores que contienen las filas, en orden:

1
2
3
4
5
dictionaryData = {
    'columnName1' : [valueForRow1, valueForRow2, valueForRow3...],
    'columnName2' : [valueForRow1, valueForRow2, valueForRow3...],
    ....
}

Representemos los mismos datos que antes, pero usando el formato de diccionario:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
dictionaryData = {
    'Scoville' : [50, 5000, 500000],
    'Name' : ["Bell pepper", "Espelette pepper", "Chocolate habanero"],
    'Feeling' : ["Not even spicy", "Uncomfortable", "Practically ate pepper spray"]
}

dataFrame1 = pd.DataFrame(dictionaryData)

# Print the dataframe
dataFrame1

Lo que nos da el resultado esperado:

creating dataframes from dictionaries

Lectura de un marco de datos desde un archivo

Hay muchos tipos de archivos admitidos para leer y escribir DataFrames. Cada función de tipo de archivo respectivo sigue la misma sintaxis read_filetype(), como read_csv(), read_excel(), read_json(), read_html(), etc...

Un tipo de archivo muy común es .csv (valores separados por comas). Las filas se proporcionan como líneas, con los valores que se supone que contienen separados por un delimitador (la mayoría de las veces, una coma). Puede establecer otro delimitador a través del argumento sep.

Si no está familiarizado con el tipo de archivo .csv, este es un ejemplo de cómo se ve:

1
2
3
4
5
6
7
Scoville, Name, Feeling
50, Bell pepper, Not even spicy 
5.000, Espelette pepper, Uncomfortable
10.000, Serrano pepper, I regret this
60.000, Bird's eye chili, 4th stage of grief 
500.000, Chocolate habanero, Practically ate pepper spray
2.000.000, Carolina Reaper, Actually ate pepper spray

Tenga en cuenta que la primera línea del archivo son los nombres de las columnas. Por supuesto, puede especificar desde qué línea Pandas debe comenzar a leer los datos, pero, de forma predeterminada, Pandas trata la primera línea como los nombres de las columnas y comienza a cargar los datos desde la segunda línea:

1
2
3
4
5
6
7
8
9
import pandas as pd

pepperDataFrame = pd.read_csv('pepper_example.csv')

# For other separators, provide the `sep` argument
# pepperDataFrame = pd.read_csv('pepper_example.csv', sep=';')

pepperDataFrame
#print(pepperDataFrame)

Lo que nos da la salida:

reading a file into a dataframe

Manipulación de tramas de datos {#manipulación de tramas de datos}

Esta sección cubrirá los métodos básicos para cambiar la estructura de un DataFrame. Sin embargo, antes de entrar en ese tema, debe saber cómo acceder a filas individuales o grupos de filas, así como a columnas.

Acceder/Localizar elementos

Pandas tiene dos formas diferentes de seleccionar datos: loc[] y iloc[].

loc[] te permite seleccionar filas y columnas usando etiquetas, como row['Value'] y column['Other Value']. Mientras tanto, iloc[] requiere que pase el índice de las entradas que desea seleccionar, por lo que solo puede usar números. También puede seleccionar columnas simplemente pasando su nombre entre paréntesis. Veamos cómo funciona esto en acción:

1
2
3
4
5
# Location by label
# Here, '5' is treated as the *label* of the index, not its value
print(pepperDataFrame.loc[5])
# Location by index
print(pepperDataFrame.iloc[1]) 

Producción:

1
2
3
4
5
6
7
8
Scoville               2.000.000
 Name                  Carolina Reaper
 Feeling               Actually ate pepper spray
Name: 5, dtype: object
Scoville               5.000
 Name                  Espelette pepper
 Feeling               Uncomfortable
Name: 1, dtype: object

Esto también funciona para un grupo de filas, como de 0...n:

1
print(pepperDataFrame.loc[:1]) 

Esto da como resultado:

python pandas loc

Es importante tener en cuenta que iloc[] siempre espera un número entero. loc[] también admite otros tipos de datos. Aquí también podemos usar un número entero, aunque también podemos usar otros tipos de datos, como cadenas.

También puede acceder a valores específicos para elementos. Por ejemplo, es posible que queramos acceder al elemento en la segunda fila, aunque solo devuelva su valor Nombre:

1
print(pepperDataFrame.loc[2, 'Name'])

Esto devuelve:

1
Chocolate habanero

Acceder a las columnas es tan simple como escribir dataFrameName.ColumnName o dataFrameName['ColumnName']. Se prefiere la segunda opción ya que la columna puede tener el mismo nombre que un método Pandas predefinido, y usar la primera opción en ese caso podría causar errores:

1
2
print(pepperDataFrame['Name']) 
# Same output as print(pepperDataFrame.Name)

Esto da como resultado:

1
2
3
4
0           Bell pepper
1      Espelette pepper
2    Chocolate habanero
Name: Name, dtype: object

También se puede acceder a las columnas usando loc[] y iloc[]. Por ejemplo, accederemos a todas las filas, desde 0...n donde n es el número de filas y buscaremos la primera columna. Esto tiene el mismo resultado que la línea de código anterior:

1
dataFrame1.iloc[:, 1] # or dataFrame1.loc[:, 'Name']

Manipulación de índices

Los índices son etiquetas de fila en un DataFrame, y son lo que usamos cuando queremos acceder a las filas. Dado que no cambiamos los índices predeterminados que Pandas asigna a los DataFrames al momento de su creación, todas nuestras filas han sido etiquetadas con números enteros desde 0 en adelante.

La primera forma en que podemos cambiar la indexación de nuestro DataFrame es usando el método set_index(). Pasamos cualquiera de las columnas de nuestro DataFrame a este método y se convierte en el nuevo índice. Entonces podemos crear índices nosotros mismos o simplemente asignar una columna como índice.

Tenga en cuenta que el método no cambia el ‘DataFrame’ original, sino que devuelve un nuevo ‘DataFrame’ con el nuevo índice, por lo que tenemos que asignar el valor de retorno a la variable ‘DataFrame’ si queremos mantener el cambio, o establezca el indicador inplace en True:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd

listPepper = [
  {'Scoville' : 50, 'Name' : 'Bell pepper', 'Feeling' : 'Not even spicy'},
  {'Scoville' : 5000, 'Name' : 'Espelette pepper', 'Feeling' : 'Uncomfortable'},
  {'Scoville' : 500000, 'Name' : 'Chocolate habanero', 'Feeling' : 'Practically ate pepper spray'},
]

dataFrame1 = pd.DataFrame(listPepper)
dataFrame2 = dataFrame1.set_index('Scoville')

dataFrame2

Producción:

python pandas set index

Esto funcionaría igual de bien:

1
2
3
4
dataFrame1 = pd.DataFrame(listPepper)
dataFrame1.set_index('Scoville', inplace=True)

dataFrame1

Ahora que tenemos un índice no predeterminado, podemos usar un nuevo conjunto de valores, usando reindex(), Pandas automáticamente llenará los valores con NaN para cada índice que no pueda coincidir con una fila existente:

1
2
new_index = [50, 5000, 'New value not present in the data frame']
dataFrame1.reindex(new_index)

Producción:

python pandas reindex

Puede controlar qué valor usa Pandas para completar los valores faltantes configurando el parámetro opcional fill_value:

1
dataFrame1.reindex(new_index, fill_value=0)

Producción:

python pandas fill value

Dado que hemos establecido un nuevo índice para nuestro DataFrame, loc[] ahora funciona con ese índice:

1
2
dataFrame1.loc[5000] 
# dataFrame1.iloc[5000] outputs the same in this case

Esto resulta en:

1
2
3
Name       Espelette pepper
Feeling       Uncomfortable
Name: 5000, dtype: object

Manipulación de filas

Agregar y eliminar filas se vuelve simple si se siente cómodo usando loc[]. Si establece una fila que no existe, se crea:

1
2
dataFrame1.loc[50] = [10000, 'Serrano pepper', 'I regret this']
dataFrame1

Producción:

python pandas loc output

Y si desea eliminar una fila, especifique su índice en la función drop(). Toma un parámetro opcional, axis. El eje acepta 0/índice o 1/columnas. Dependiendo de esto, la función drop() descarta la fila a la que se llama o la columna a la que se llama.

Si no se especifica un valor para el parámetro axis, se eliminará la fila correspondiente de forma predeterminada, ya que axis es 0 de forma predeterminada:

1
2
dataFrame1.drop(1, inplace=True) 
# Same as dataFrame1.drop(1, axis=0)

Producción:

python pandas drop function

También puede cambiar el nombre de las filas que ya existen en la tabla. La función rename() acepta un diccionario de cambios que deseas hacer:

1
dataFrame1.rename({0:"First", 1:"Second"}, inplace=True)

Producción:

python pandas rename

Tenga en cuenta que drop() y rename() también aceptan el parámetro opcional - inplace. Establecer esto en True (False de forma predeterminada) le indicará a Pandas que cambie el DataFrame original en lugar de devolver uno nuevo. Si no se configura, tendrá que empaquetar el DataFrame resultante en uno nuevo para conservar los cambios.

Otro método útil que debe tener en cuenta es la función drop_duplicates() que elimina todas las filas duplicadas del DataFrame. Demostremos esto agregando dos filas duplicadas:

1
2
3
4
dataFrame1.loc[3] = [60.000, "Bird's eye chili", "4th stage of grief"]
dataFrame1.loc[4] = [60.000, "Bird's eye chili", "4th stage of grief"]

dataFrame1

Lo que nos da la salida:

python pandas add duplicate

Ahora podemos llamar a drop_duplicates():

1
2
3
dataFrame1.drop_duplicates(inplace=True)

dataFrame1

Y las filas duplicadas serán eliminadas:
python pandas remove duplicate

Manipulación de columnas

Se pueden agregar nuevas columnas de forma similar a como se agregan filas:

1
2
dataFrame1['Color'] = ['Green', 'Bright Red', 'Brown']
dataFrame1

Producción:

python pandas manipulate columns

También de manera similar a las filas, las columnas se pueden eliminar llamando a la función drop(), la única diferencia es que debe establecer el parámetro opcional axis en 1 para que Pandas sepa que desea eliminar una columna y no una fila:

1
dataFrame1.drop('Feeling', axis=1, inplace=True)

Producción:

python pandas drop inplace

Cuando se trata de renombrar columnas, la función rename() necesita que se le diga específicamente que queremos cambiar las columnas configurando el parámetro opcional columns al valor de nuestro "cambiar diccionario":

1
dataFrame1.rename(columns={"Feeling":"Measure of Pain"}, inplace=True)

Producción:

python pandas rename column

Nuevamente, al igual que con la eliminación/cambio de nombre de las filas, puede establecer el parámetro opcional ‘inplace’ en ‘True’ si desea que se modifique el ‘DataFrame’ original en lugar de que la función devuelva un nuevo ‘DataFrame’.

Conclusión

En este artículo, hemos repasado lo que son los marcos de datos de Pandas, ya que son una clase clave del marco de trabajo de Pandas que se utiliza para almacenar datos.

Hemos aprendido cómo crear un DataFrame manualmente, usando una lista y un diccionario, después de lo cual hemos leído los datos de un archivo.

Luego, manipulamos los datos en DataFrame - usando loc[] y iloc[], localizamos datos, creamos nuevas filas y columnas, cambiamos el nombre de las existentes y luego las soltamos.