Explorando y analizando DataFrames con Pandas
Contenido
Explorando y analizando DataFrames con Pandas¶
Pandas es un paquete construido sobre la base de NumPy, incluye la implementación de la estructura DataFrame. Un DataFrame es, en esencia, un arreglo bidimensional con etiquetas para filas y columnas, típicamente las columnas contienen tipo de datos diferentes.
import numpy as np
import pandas as pd
Series¶
Un objecto de tipo Series es un arreglo de datos, parecido a un Array de numpy, que consta de índices y valores.
Aquí algunos enlaces de referencia:
https://pandas.pydata.org/pandas-docs/stable/reference/series.html#computations-descriptive-stats
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html
Una serie tiene varios métodos, como min, mean, std
, entre muchos otros. Para crear una serie:
serie = pd.Series([0.25, 0.5, 0.75, 1.0])
print(serie)
print('Desviación estándar: ', serie.std())
0 0.25
1 0.50
2 0.75
3 1.00
dtype: float64
Desviación estándar: 0.3227486121839514
Una serie tiene valores e índices:
print('Valores: ', serie.values)
print('Índices: ', serie.index)
Valores: [0.25 0.5 0.75 1. ]
Índices: RangeIndex(start=0, stop=4, step=1)
Filtrado de datos, retorna una Serie de valores booleanos:
serie > 0.5
0 False
1 False
2 True
3 True
dtype: bool
serie.isnull()
0 False
1 False
2 False
3 False
dtype: bool
A diferencia de los arreglos de Numpy, a una Serie se le puede asignar un indice de manera explícta:
serie = pd.Series([0.25, 0.5, 0.75, 1.0], index=['a', 'b', 'c', 'd'])
print(serie['a':'c'])
a 0.25
b 0.50
c 0.75
dtype: float64
Se puede crear una Serie a partir de un diccionario (clave -> indice)
poblacion_dict = {'Chuquisaca': 626000,
'La Paz': 26448193,
'Cochabamba': 2883000,
'Oruro': 538000,
'Potosí': 887000,
'Tarija': 563000,
'Santa Cruz': 3225000,
'Beni': 468000,
'Pando': 144000 }
poblacion = pd.Series(poblacion_dict)
poblacion
Chuquisaca 626000
La Paz 26448193
Cochabamba 2883000
Oruro 538000
Potosí 887000
Tarija 563000
Santa Cruz 3225000
Beni 468000
Pando 144000
dtype: int64
Otros ejemplos de creación de Series
serie = pd.Series(5, index=[100, 200, 300])
serie
100 5
200 5
300 5
dtype: int64
Selección de claves del diccionario (solo se crea un serie con una parte del diccionario)
serie = pd.Series({2:'a', 1:'b', 3:'c'}, index=[3, 2])
serie
3 c
2 a
dtype: object
Dataframes¶
Un DataFrame es un arreglo bi-dimensional formado por una secuencia de Series con la misma cantidad de elementos y con el mismo índice. Es decir: es como un diccionario de Series del mismo tamaño y con los mismos índices. Un DataFrame permite asignar nombres a las columnas.
extension_departamentos_Bolivia_dict = {'Chuquisaca': 51514,
'La Paz': 133985,
'Cochabamba': 55631,
'Oruro': 55588,
'Potosí': 117218,
'Tarija': 37623,
'Santa Cruz': 370621,
'Beni': 213564
}
extension_departamentos_Serie = pd.Series(extension_departamentos_Bolivia_dict)
extension_departamentos_Serie
Chuquisaca 51514
La Paz 133985
Cochabamba 55631
Oruro 55588
Potosí 117218
Tarija 37623
Santa Cruz 370621
Beni 213564
dtype: int64
Creación a partir de dos Series que tiene el mismo index (aunque los indices no estén en el mismo order o incluso falten datos en algunas de las Series)
datos_bolivia = pd.DataFrame({'poblacion': poblacion, 'extension': extension_departamentos_Serie})
datos_bolivia
poblacion | extension | |
---|---|---|
Beni | 468000 | 213564.0 |
Chuquisaca | 626000 | 51514.0 |
Cochabamba | 2883000 | 55631.0 |
La Paz | 26448193 | 133985.0 |
Oruro | 538000 | 55588.0 |
Pando | 144000 | NaN |
Potosí | 887000 | 117218.0 |
Santa Cruz | 3225000 | 370621.0 |
Tarija | 563000 | 37623.0 |
Tanto las filas como las columnas tienen asociado un índice
print(datos_bolivia.index)
print(datos_bolivia.columns)
Index(['Beni', 'Chuquisaca', 'Cochabamba', 'La Paz', 'Oruro', 'Pando',
'Potosí', 'Santa Cruz', 'Tarija'],
dtype='object')
Index(['poblacion', 'extension'], dtype='object')
Se puede ver a un DataFrame como un diccionario de Series (columnas)
datos_bolivia['poblacion']
Beni 468000
Chuquisaca 626000
Cochabamba 2883000
La Paz 26448193
Oruro 538000
Pando 144000
Potosí 887000
Santa Cruz 3225000
Tarija 563000
Name: poblacion, dtype: int64
Otras maneras de crear un DataFrame: si no se provee un índice se crea una secuencia de numeros que empieza en 0.
data = pd.DataFrame(columns=['a','b'], data=[[1, 45], [87, 96], [125, 13], [135, 789]])
data
a | b | |
---|---|---|
0 | 1 | 45 |
1 | 87 | 96 |
2 | 125 | 13 |
3 | 135 | 789 |
Lista de diccionarios (las claves son los nombres de las columnas)
data = pd.DataFrame([{'a': 1, 'b': 2}, {'b': 3, 'c': 4}])
data
a | b | c | |
---|---|---|---|
0 | 1.0 | 2 | NaN |
1 | NaN | 3 | 4.0 |
Información general de un DataFrame
datos_bolivia.shape
(9, 2)
datos_bolivia.head(5)
poblacion | extension | |
---|---|---|
Beni | 468000 | 213564.0 |
Chuquisaca | 626000 | 51514.0 |
Cochabamba | 2883000 | 55631.0 |
La Paz | 26448193 | 133985.0 |
Oruro | 538000 | 55588.0 |
datos_bolivia.tail(5)
poblacion | extension | |
---|---|---|
Oruro | 538000 | 55588.0 |
Pando | 144000 | NaN |
Potosí | 887000 | 117218.0 |
Santa Cruz | 3225000 | 370621.0 |
Tarija | 563000 | 37623.0 |
datos_bolivia.size
18
datos_bolivia.info()
<class 'pandas.core.frame.DataFrame'>
Index: 9 entries, Beni to Tarija
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 poblacion 9 non-null int64
1 extension 8 non-null float64
dtypes: float64(1), int64(1)
memory usage: 516.0+ bytes
# la función describe() devuele un DataFrame con indicadores para cada una de las columnas
datos_bolivia.describe()
poblacion | extension | |
---|---|---|
count | 9.000000e+00 | 8.000000 |
mean | 3.975799e+06 | 129468.000000 |
std | 8.499862e+06 | 113904.633998 |
min | 1.440000e+05 | 37623.000000 |
25% | 5.380000e+05 | 54569.500000 |
50% | 6.260000e+05 | 86424.500000 |
75% | 2.883000e+06 | 153879.750000 |
max | 2.644819e+07 | 370621.000000 |
Indices¶
Un Index es el mecanismo para referenciar datos en las Series y los DataFrames. Un Index object es un conjunto ordenado de valores
indA = pd.Index([1, 3, 5, 7, 9])
indB = pd.Index([2, 3, 5, 7, 11])
print(indA.union(indB))
print(indA.intersection(indB))
print(indA.difference(indB))
Int64Index([1, 2, 3, 5, 7, 9, 11], dtype='int64')
Int64Index([3, 5, 7], dtype='int64')
Int64Index([1, 9], dtype='int64')
Extracción de datos¶
Extraer datos de un DataFrame o una serie.
datos_bolivia = pd.DataFrame(data={'poblacion':poblacion, 'extension':extension_departamentos_Serie})
datos_bolivia
poblacion | extension | |
---|---|---|
Beni | 468000 | 213564.0 |
Chuquisaca | 626000 | 51514.0 |
Cochabamba | 2883000 | 55631.0 |
La Paz | 26448193 | 133985.0 |
Oruro | 538000 | 55588.0 |
Pando | 144000 | NaN |
Potosí | 887000 | 117218.0 |
Santa Cruz | 3225000 | 370621.0 |
Tarija | 563000 | 37623.0 |
Un DataFrame es como diccionario de Series (columnas) en el cual se puede extraer y modificar datos
datos_bolivia['poblacion']
datos_bolivia[['poblacion','extension']]
datos_bolivia['constante'] = 1
datos_bolivia['densidad'] = datos_bolivia['poblacion'] / datos_bolivia['extension']
datos_bolivia
poblacion | extension | constante | densidad | |
---|---|---|---|---|
Beni | 468000 | 213564.0 | 1 | 2.191381 |
Chuquisaca | 626000 | 51514.0 | 1 | 12.152036 |
Cochabamba | 2883000 | 55631.0 | 1 | 51.823624 |
La Paz | 26448193 | 133985.0 | 1 | 197.396671 |
Oruro | 538000 | 55588.0 | 1 | 9.678348 |
Pando | 144000 | NaN | 1 | NaN |
Potosí | 887000 | 117218.0 | 1 | 7.567097 |
Santa Cruz | 3225000 | 370621.0 | 1 | 8.701612 |
Tarija | 563000 | 37623.0 | 1 | 14.964251 |
datos_bolivia['capital'] = pd.Series(
{'Chuquisaca': 'Sucre',
'La Paz': 'Murillo',
'Cochabamba': 'Cercado',
'Oruro': 'Cercado',
'Potosí': 'Potosí',
'Tarija': 'Tarija',
'Santa Cruz': 'Santa Cruz de la Sierra',
'Pando': 'Cobija',
'Beni': 'Trinidad' })
datos_bolivia
poblacion | extension | constante | densidad | capital | |
---|---|---|---|---|---|
Beni | 468000 | 213564.0 | 1 | 2.191381 | Trinidad |
Chuquisaca | 626000 | 51514.0 | 1 | 12.152036 | Sucre |
Cochabamba | 2883000 | 55631.0 | 1 | 51.823624 | Cercado |
La Paz | 26448193 | 133985.0 | 1 | 197.396671 | Murillo |
Oruro | 538000 | 55588.0 | 1 | 9.678348 | Cercado |
Pando | 144000 | NaN | 1 | NaN | Cobija |
Potosí | 887000 | 117218.0 | 1 | 7.567097 | Potosí |
Santa Cruz | 3225000 | 370621.0 | 1 | 8.701612 | Santa Cruz de la Sierra |
Tarija | 563000 | 37623.0 | 1 | 14.964251 | Tarija |
Un DataFrame es también como un arreglo bidimensional (una matriz de Series) Soporta indices, slicing, filtering empleando los indices explicitos (iloc usa indices numéricos implicitos). El primer valor de la matriz hace referencia a las filas
https://railsware.com/blog/python-for-machine-learning-indexing-and-slicing-for-lists-tuples-strings-and-other–sequential-types/
datos_bolivia.loc['Beni']
poblacion 468000
extension 213564.0
constante 1
densidad 2.191381
capital Trinidad
Name: Beni, dtype: object
datos_bolivia.loc['Beni':'Oruro']
poblacion | extension | constante | densidad | capital | |
---|---|---|---|---|---|
Beni | 468000 | 213564.0 | 1 | 2.191381 | Trinidad |
Chuquisaca | 626000 | 51514.0 | 1 | 12.152036 | Sucre |
Cochabamba | 2883000 | 55631.0 | 1 | 51.823624 | Cercado |
La Paz | 26448193 | 133985.0 | 1 | 197.396671 | Murillo |
Oruro | 538000 | 55588.0 | 1 | 9.678348 | Cercado |
datos_bolivia['poblacion'] > 2000000
Beni False
Chuquisaca False
Cochabamba True
La Paz True
Oruro False
Pando False
Potosí False
Santa Cruz True
Tarija False
Name: poblacion, dtype: bool
datos_bolivia['extension'].isnull()
Beni False
Chuquisaca False
Cochabamba False
La Paz False
Oruro False
Pando True
Potosí False
Santa Cruz False
Tarija False
Name: extension, dtype: bool
Se utiliza (&, |) en lugar de (and, or)¶
datos_bolivia.loc[(datos_bolivia['poblacion'] > 2000000) & (datos_bolivia['extension']> 60000.0), ['poblacion','densidad'] ]
datos_bolivia
poblacion | extension | constante | densidad | capital | |
---|---|---|---|---|---|
Beni | 468000 | 213564.0 | 1 | 2.191381 | Trinidad |
Chuquisaca | 626000 | 51514.0 | 1 | 12.152036 | Sucre |
Cochabamba | 2883000 | 55631.0 | 1 | 51.823624 | Cercado |
La Paz | 26448193 | 133985.0 | 1 | 197.396671 | Murillo |
Oruro | 538000 | 55588.0 | 1 | 9.678348 | Cercado |
Pando | 144000 | NaN | 1 | NaN | Cobija |
Potosí | 887000 | 117218.0 | 1 | 7.567097 | Potosí |
Santa Cruz | 3225000 | 370621.0 | 1 | 8.701612 | Santa Cruz de la Sierra |
Tarija | 563000 | 37623.0 | 1 | 14.964251 | Tarija |
Modificación de datos¶
Elimina todos los datos de una columna
datos_bolivia.drop(columns=['constante'], inplace=True)
datos_bolivia
poblacion | extension | densidad | capital | |
---|---|---|---|---|
Beni | 468000 | 213564.0 | 2.191381 | Trinidad |
Chuquisaca | 626000 | 51514.0 | 12.152036 | Sucre |
Cochabamba | 2883000 | 55631.0 | 51.823624 | Cercado |
La Paz | 26448193 | 133985.0 | 197.396671 | Murillo |
Oruro | 538000 | 55588.0 | 9.678348 | Cercado |
Pando | 144000 | NaN | NaN | Cobija |
Potosí | 887000 | 117218.0 | 7.567097 | Potosí |
Santa Cruz | 3225000 | 370621.0 | 8.701612 | Santa Cruz de la Sierra |
Tarija | 563000 | 37623.0 | 14.964251 | Tarija |
Eliminar los datos faltantes (los que son NaN)
datos_bolivia.dropna(how='any')
poblacion | extension | densidad | capital | |
---|---|---|---|---|
Beni | 468000 | 213564.0 | 2.191381 | Trinidad |
Chuquisaca | 626000 | 51514.0 | 12.152036 | Sucre |
Cochabamba | 2883000 | 55631.0 | 51.823624 | Cercado |
La Paz | 26448193 | 133985.0 | 197.396671 | Murillo |
Oruro | 538000 | 55588.0 | 9.678348 | Cercado |
Potosí | 887000 | 117218.0 | 7.567097 | Potosí |
Santa Cruz | 3225000 | 370621.0 | 8.701612 | Santa Cruz de la Sierra |
Tarija | 563000 | 37623.0 | 14.964251 | Tarija |
datos_bolivia.loc['Pando', 'densidad'] = datos_bolivia.loc['Pando', 'poblacion'] / datos_bolivia.loc['Pando', 'extension']
datos_bolivia
poblacion | extension | densidad | capital | |
---|---|---|---|---|
Beni | 468000 | 213564.0 | 2.191381 | Trinidad |
Chuquisaca | 626000 | 51514.0 | 12.152036 | Sucre |
Cochabamba | 2883000 | 55631.0 | 51.823624 | Cercado |
La Paz | 26448193 | 133985.0 | 197.396671 | Murillo |
Oruro | 538000 | 55588.0 | 9.678348 | Cercado |
Pando | 144000 | NaN | NaN | Cobija |
Potosí | 887000 | 117218.0 | 7.567097 | Potosí |
Santa Cruz | 3225000 | 370621.0 | 8.701612 | Santa Cruz de la Sierra |
Tarija | 563000 | 37623.0 | 14.964251 | Tarija |
Apply¶
Appy aplica una función que recibe como argumento a cada una de las columnas (o filas) de un DataFrame. Modifica el DataFrame existente.
axis=0 es la opción por defecto, significa que se recorrerá el DataFrame por las columnas (similar a recorrer una matriz por columas). Si axis=1 el DataFrame se recorrerá por sus filas.
datos_bolivia_extension_reducida_a_la_mitad = datos_bolivia.apply(lambda x: x['extension']/2, axis=1)
datos_bolivia_extension_reducida_a_la_mitad
Beni 106782.0
Chuquisaca 25757.0
Cochabamba 27815.5
La Paz 66992.5
Oruro 27794.0
Pando NaN
Potosí 58609.0
Santa Cruz 185310.5
Tarija 18811.5
dtype: float64
One Hot Encoding¶
Conversión de valores numéricos y nominales en categorías y luego las categorías en valores numéricos. Necesario cuando el algoritmo de aprendizaje automático no es capaz de trabajar con valores nominales o contínuos
Obtener los códigos de una variable nominal
datos_bolivia['capital'].astype('category').cat.codes
Beni 7
Chuquisaca 5
Cochabamba 0
La Paz 2
Oruro 0
Pando 1
Potosí 3
Santa Cruz 4
Tarija 6
dtype: int8
Obtener el vector One Hot Encoding
pd.get_dummies(datos_bolivia,columns=['capital'])
poblacion | extension | densidad | capital_Cercado | capital_Cobija | capital_Murillo | capital_Potosí | capital_Santa Cruz de la Sierra | capital_Sucre | capital_Tarija | capital_Trinidad | |
---|---|---|---|---|---|---|---|---|---|---|---|
Beni | 468000 | 213564.0 | 2.191381 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Chuquisaca | 626000 | 51514.0 | 12.152036 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
Cochabamba | 2883000 | 55631.0 | 51.823624 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
La Paz | 26448193 | 133985.0 | 197.396671 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
Oruro | 538000 | 55588.0 | 9.678348 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Pando | 144000 | NaN | NaN | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
Potosí | 887000 | 117218.0 | 7.567097 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Santa Cruz | 3225000 | 370621.0 | 8.701612 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
Tarija | 563000 | 37623.0 | 14.964251 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |