PANDAS - Manipulacion de Datos con Python

Por Jose R. Zapata

Ultima actualizacion: 11/Nov/2023

Invitame a un Cafe

Pandas es una herramienta de manipulación de datos de alto nivel desarrollada por Wes McKinney. Es construido sobre Numpy y permite el análisis de datos que cuenta con las estructuras de datos que necesitamos para limpiar los datos en bruto y que sean aptos para el análisis (por ejemplo, tablas). Como Pandas permite realizar tareas importantes, como alinear datos para su comparación, fusionar conjuntos de datos, gestión de datos perdidos, etc., se ha convertido en una librería muy importante para procesar datos a alto nivel en Python (es decir, estadísticas ). Pandas fue diseñada originalmente para gestionar datos financieros, y como alternativo al uso de hojas de cálculo (es decir, Microsoft Excel).

Los principales tipos de datos que pueden representarse con pandas son:

  • Datos tabulares con columnas de tipo heterogéneo con etiquetas en columnas y filas.
  • Series temporales

Pandas proporciona herramientas que permiten:

  • leer y escribir datos en diferentes formatos: CSV, JSON, Excel, bases SQL, parquet y HDF5 entre otros
  • seleccionar y filtrar de manera sencilla tablas de datos en función de posición, valor o etiquetas
  • fusionar y unir datos
  • transformar datos aplicando funciones tanto en global como por ventanas
  • manipulación de series temporales
  • hacer gráficas

En pandas existen tres tipos básicos de objetos todos ellos basados a su vez en Numpy:

  • Series (listas, 1D)
  • DataFrame (tablas, 2D)

Por lo tanto, Pandas nos proporciona las estructuras de datos y funciones necesarias para el análisis de datos.

Instalar Pandas

Pandas ya esta preinstalado si se usa Google Collaboratory, si va realizar una instalacion en su computador

PIP

pip install pandas
Este Tutorial esta con Pandas version 1.5.3 , debido a que es la version que usa Google Collaboratory y donde se desarrollan las practicas de este curso, se recomienda estar pendiente de cuando se cambie este tutorial a Pandas version 2.x.x que ya esta disponible, es mas rapido pero tiene cambios que en algunos casos no es compatible con la version 1.5.3

Importando Pandas

La libreria Pandas se importa de la siguiente manera

import pandas as pd # Importacion estandar de la libreria Pandas
import numpy  as np # Importacion estandar de la libreria NumPy
pd.__version__
'1.5.3'

Series

Una serie es el primer tipo de datos de pandas y es muy similar a una matriz NumPy (de hecho está construida sobre el objeto de matriz NumPy). Lo que diferencia un arreglo NumPy de una serie, es que una serie puede tener etiquetas en los ejes, lo que significa que puede ser indexada por una etiqueta, en lugar de solo una ubicación numérica. Tampoco necesita contener datos numéricos, puede contener cualquier Objeto de Python arbitrario.

Creando una Serie

Puede convertir una lista, una matriz numpy o un diccionario en una serie, usando el metodo pd.Series:

# Crear diferentes tipos de datos
labels = ['a','b','c'] # lista de eetiquetas
my_list = [10,20,30] # lista con valores
arr = np.array([10,20,30]) # Convertir ista de valores en arreglo NumPy
d = {'a':10,'b':20,'c':30} # Creacion de un diccionario

Desde Listas

# Convertir una lista en series usando el metodo pd.Series
# observe que se crean los nombres con las posiciones de cada elemento
pd.Series(data=my_list)
0    10
1    20
2    30
dtype: int64
# Convertir una lista en series usando el metodo pd.Series
# se puede ingresar el nombre de las posiciones
pd.Series(data=my_list,index=labels)
a    10
b    20
c    30
dtype: int64
# No es necesario ingresar la palabra de 'data =''  en el argumento
pd.Series(my_list,labels)
a    10
b    20
c    30
dtype: int64

Desde Arreglos NumPy

# Convertir un arreglo en series usando el metodo pd.Series
pd.Series(arr)
0    10
1    20
2    30
dtype: int64
# Convertir un arreglo en series indicando tambien los valores del index
pd.Series(arr,labels)
a    10
b    20
c    30
dtype: int64

Desde un Diccionario

# Convertir un diccionario en series usando el metodo pd.Series
# Como el diccionario ya tiene clave entonces se le asigna como valor de la posicion
pd.Series(d)
a    10
b    20
c    30
dtype: int64

Datos en una Series

Una serie de pandas puede contener una variedad de tipos de objetos:

# Creando una serie basado solo en una lista de letras
pd.Series(data=labels)
0    a
1    b
2    c
dtype: object

Indexacion

La clave para usar una serie es entender su índice. Pandas hace uso de estos nombres o números de índice al permitir búsquedas rápidas de información (funciona como una tabla hash o diccionario).

Veamos algunos ejemplos de cómo obtener información de una serie. Vamos a crear dos series, ser1 y ser2:

# Creacion de una serie con sus labels o indices
ser1 = pd.Series([1,2,3,4],
                 index = ['USA', 'Alemania','Italia', 'Japon'])                                   
ser1
USA         1
Alemania    2
Italia      3
Japon       4
dtype: int64
# Creacion de una serie con sus labels o indices
ser2 = pd.Series([1,2,5,4],
                 index = ['USA', 'Alemania','Colombia', 'Japon'])                                   
ser2
USA         1
Alemania    2
Colombia    5
Japon       4
dtype: int64
# La busqueda en una serie es igual como en un diccionario
ser1['USA']
1
# La busqueda en una serie es igual como en un diccionario
ser2['Colombia']
5

Las operaciones también se realizan según el índice:

# Observe los resultados de los paises que solo estan en una serie y no en las dos
ser1 + ser2
Alemania    4.0
Colombia    NaN
Italia      NaN
Japon       8.0
USA         2.0
dtype: float64

DataFrames

Los DataFrames son la estructura mas importante en pandas y están directamente inspirados en el lenguaje de programación R. Se puede pensar en un DataFrame como un conjunto de Series reunidas que comparten el mismo índice. En los DataFrame tenemos la opción de especificar tanto el index (el nombre de las filas) como columns (el nombre de las columnas).

# Importar la funcion de NumPy para crear arreglos de numeros enteros
from numpy.random import randn
np.random.seed(101) # Inicializar el generador aleatorio
# Forma rapida de crear una lista de python desde strings
'A B C D E F'.split()
['A', 'B', 'C', 'D', 'E']
# Crear un dataframe con numeros aleatorios de 4 Columnas y 5 Filas
# Crear listas rapidamente usando la funcion split 'A B C D E'.split()
# Esto evita tener que escribir repetidamente las comas

df = pd.DataFrame(randn(6,4),
                  index='A B C D E F'.split(),
                  columns='W X Y Z'.split())
df

WXYZ
A-0.9932630.196800-1.1366450.000366
B1.025984-0.156598-0.0315790.649826
C2.154846-0.610259-0.755325-0.346419
D0.147027-0.4794480.5587691.024810
E-0.9258741.862864-1.1338170.610478
F0.3860302.084019-0.3765190.230336

Descripcion general del dataframe

Numero de Filas y Columnas

df.shape # retorna un Tuple asi: (filas, col)
(6, 4)

Informacion General de los datos

# Informacion general de los datos de cada cloumna
# Indica el numero de filas del dataset
# Muestra el numero de datos No Nulos por columna (valores validos)
# Tipo de dato de cada columna
# Tamaño total del dataset
df.info()
<class 'pandas.core.frame.DataFrame'>
Index: 6 entries, A to F
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   W       6 non-null      float64
 1   X       6 non-null      float64
 2   Y       6 non-null      float64
 3   Z       6 non-null      float64
dtypes: float64(4)
memory usage: 240.0+ bytes
# Tipos de datos que existen en las columnas del dataframe
df.dtypes
W    float64
X    float64
Y    float64
Z    float64
dtype: object

Resumen de estadistica descriptiva General

el metodo .describe() de los dataframes presenta un resumen de la estadistica descriptiva general de las columnas numericas del dataframe, presenta la informacion de:

  • Promedio (mean)
  • Desviacion estandard (std)
  • Valor minimo
  • Valor maximo
  • Cuartiles (25%, 50% y 75%)
df.describe() # No muestra la informacion de las columnas categoricas

WXYZ
count6.0000006.0000006.0000006.000000
mean0.2991250.482896-0.4791860.361566
std1.1977981.1899410.6671270.496764
min-0.993263-0.610259-1.136645-0.346419
25%-0.657649-0.398736-1.0391940.057859
50%0.2665290.020101-0.5659220.420407
75%0.8659961.446348-0.1178140.639989
max2.1548462.0840190.5587691.024810

Ver Primeros elementos del dataframe

df.head()

WXYZ
A-0.9932630.196800-1.1366450.000366
B1.025984-0.156598-0.0315790.649826
C2.154846-0.610259-0.755325-0.346419
D0.147027-0.4794480.5587691.024810
E-0.9258741.862864-1.1338170.610478

Ver Ultimos elementos del dataframe

df.tail()

WXYZ
B1.025984-0.156598-0.0315790.649826
C2.154846-0.610259-0.755325-0.346419
D0.147027-0.4794480.5587691.024810
E-0.9258741.862864-1.1338170.610478
F0.3860302.084019-0.3765190.230336

Ver elementos aleatorios del dataframe

df.sample(3)

WXYZ
A-0.9932630.196800-1.1366450.000366
E-0.9258741.862864-1.1338170.610478
D0.147027-0.4794480.5587691.024810

Seleccion y Indexacion

Existen diversos métodos para tomar datos de un DataFrame

# Regresara todos los datos de la columna W
df['W']
A    2.706850
B    0.651118
C   -2.018168
D    0.188695
E    0.190794
Name: W, dtype: float64
# Seleccionar dos o mas columnas
# Pasar una lista con los nombres de las columnas

df[['W','Z']]

WZ
A2.7068500.503826
B0.6511180.605965
C-2.018168-0.589001
D0.1886950.955057
E0.1907940.683509
# Seleccionar dos o mas columnas
# Pasar una lista con los nombres de las columnas
# Puedo indicar el orden de las columnas

df[['X','W','Z']] 

XWZ
A0.6281332.7068500.503826
B-0.3193180.6511180.605965
C0.740122-2.018168-0.589001
D-0.7588720.1886950.955057
E1.9787570.1907940.683509

Las columnas de un DataFrame Columns son solo Series

type(df['W']) # Tipos de datos
pandas.core.series.Series

Creando una Nueva Columna

# Nueva columna igual a la suma de otras dos
# operacion vectorizada
df['new'] = df['W'] + df['Y']
df

WXYZnew
A2.7068500.6281330.9079690.5038263.614819
B0.651118-0.319318-0.8480770.605965-0.196959
C-2.0181680.7401220.528813-0.589001-1.489355
D0.188695-0.758872-0.9332370.955057-0.744542
E0.1907941.9787572.6059670.6835092.796762

Eliminando Columnas

df.drop('new',axis='columns')

WXYZ
A2.7068500.6281330.9079690.503826
B0.651118-0.319318-0.8480770.605965
C-2.0181680.7401220.528813-0.589001
D0.188695-0.758872-0.9332370.955057
E0.1907941.9787572.6059670.683509
# No se aplica a el dataframe a menos que se especifique.
# Como se ve la operacion pasada no quedo grabada
df

WXYZnew
A2.7068500.6281330.9079690.5038263.614819
B0.651118-0.319318-0.8480770.605965-0.196959
C-2.0181680.7401220.528813-0.589001-1.489355
D0.188695-0.758872-0.9332370.955057-0.744542
E0.1907941.9787572.6059670.6835092.796762
# Para que quede grabado se puede hacer de dos formas
#df = df.drop('new',axis='columns') # Forma 1

df.drop('new', axis='columns', inplace=True) # Forma 2
df

WXYZ
A2.7068500.6281330.9079690.503826
B0.651118-0.319318-0.8480770.605965
C-2.0181680.7401220.528813-0.589001
D0.188695-0.758872-0.9332370.955057
E0.1907941.9787572.6059670.683509
df

WXYZ
A2.7068500.6281330.9079690.503826
B0.651118-0.319318-0.8480770.605965
C-2.0181680.7401220.528813-0.589001
D0.188695-0.758872-0.9332370.955057
E0.1907941.9787572.6059670.683509

También se puede sacar filas de esta manera:

df.drop('E',axis='index')

WXYZ
A2.7068500.6281330.9079690.503826
B0.651118-0.319318-0.8480770.605965
C-2.0181680.7401220.528813-0.589001
D0.188695-0.758872-0.9332370.955057
df

WXYZ
A2.7068500.6281330.9079690.503826
B0.651118-0.319318-0.8480770.605965
C-2.0181680.7401220.528813-0.589001
D0.188695-0.758872-0.9332370.955057
E0.1907941.9787572.6059670.683509
# Otra manera de borrar las columnas es
del df['X'] # Esta funcion es INPLACE
df 

WYZ
A2.7068500.9079690.503826
B0.651118-0.8480770.605965
C-2.0181680.528813-0.589001
D0.188695-0.9332370.955057
E0.1907942.6059670.683509

Obtener los nombres de las columnas y los indices (index):

df.columns # nombres de las columnas
Index(['W', 'Y', 'Z'], dtype='object')
df.index # nombres de los indices
Index(['A', 'B', 'C', 'D', 'E'], dtype='object')

Seleccionando Filas y Columnas

las dos formas de seleccion principal son:

  • DataFrame.loc[etiqueta_fila, etiqueta_columna] <- por etiquetas
  • DataFrame.iloc[indice_fila, indice_columna] <- por indices
# la funcion loc busca por medio de los nombres de los indices y columnas
df.loc['A'] # se selecciona todos los valores de la fila 'A'
W    2.706850
Y    0.907969
Z    0.503826
Name: A, dtype: float64

O basado en la posicion (index) en vez de usar la etiqueta

df.iloc[2] # Se seleccionan los valores de la fila con indice 2
# recordar que los index empiezan en cero
W   -2.018168
Y    0.528813
Z   -0.589001
Name: C, dtype: float64

Seleccionar un subconjunto de filas y columnas

# Mediante etiquetas
# se selecciona el elemento que esta en la fila=B Col=Y
df.loc['B','Y'] # con etiquetas
-0.8480769834036315
# Mediante etiquetas
# se selecciona un subconjunto de datos que estan entre
# filas = A, B   Cols= W, Y
df.loc[['A','B'],['W','Y']]

WY
A2.7068500.907969
B0.651118-0.848077
df.loc[['B','A'],['Y','W']]

YW
B-0.8480770.651118
A0.9079692.706850

Seleccion Condicional o Filtros

Una característica importante de pandas es la selección condicional usando la notación de corchetes, muy similar a NumPy:

df  

WYZ
A2.7068500.9079690.503826
B0.651118-0.8480770.605965
C-2.0181680.528813-0.589001
D0.188695-0.9332370.955057
E0.1907942.6059670.683509
# Devuelve un dataframe con booleans
# segun si se cumple o no la condicion
df>0

WYZ
ATrueTrueTrue
BTrueFalseTrue
CFalseTrueFalse
DTrueFalseTrue
ETrueTrueTrue
# Esta operacion solo mostrara los valores del dataframe que cumplen la condicion
# los que no cumplen devuelve el valor NaN
df[df>0]

WYZ
A2.7068500.9079690.503826
B0.651118NaN0.605965
CNaN0.528813NaN
D0.188695NaN0.955057
E0.1907942.6059670.683509
# seleccionar todas las filas donde el valor
# que esta en la columna 'W' sea mayor que cero
df[df['W']>0] 

WYZ
A2.7068500.9079690.503826
B0.651118-0.8480770.605965
D0.188695-0.9332370.955057
E0.1907942.6059670.683509
# Seleccionar las filas donde 'W' sea mayor que cero
# y de esas filas escoger los valores de la columna 'Y'
df[df['W']>0]['Y']
A    0.907969
B   -0.848077
D   -0.933237
E    2.605967
Name: Y, dtype: float64
# Seleccionar las filas donde 'W' sea mayor que cero
# y de esas filas escoger los valores de las columna 'Y' y 'X'
df[df['W']>0][['Y','Z']]

YZ
A0.9079690.503826
B-0.8480770.605965
D-0.9332370.955057
E2.6059670.683509

Para dos condiciones, se usa los booleanos de esta forma

  • | en vez de or
  • & en vez de and
  • ~ en vez de not

Por amor a Dios, recuerde usar paréntesis:

# Seleccionar las filas donde 'W' sea mayor que cero
# y tambien donde 'Y' sea mayor que 0.5
df[(df['W']>0) & (df['Y'] > 0.5)]

WYZ
A2.7068500.9079690.503826
E0.1907942.6059670.683509

.query() Busqueda condicional

Los terminos de busqueda condicional o filtros se entregan al metodo como tipo ‘string’

df

WYZ
A2.7068500.9079690.503826
B0.651118-0.8480770.605965
C-2.0181680.528813-0.589001
D0.188695-0.9332370.955057
E0.1907942.6059670.683509
# seleccionar todas las filas donde el valor
# que esta en la columna 'W' sea mayor que cero

#df[df['W']>0]
df.query('W>0')

WYZ
A2.7068500.9079690.503826
B0.651118-0.8480770.605965
D0.188695-0.9332370.955057
E0.1907942.6059670.683509
# Seleccionar las filas donde 'W' sea mayor que cero
# y de esas filas escoger los valores de la columna 'Y'

#df[df['W']>0]['Y']
df.query('W>0')['Y']
A    0.907969
B   -0.848077
D   -0.933237
E    2.605967
Name: Y, dtype: float64
# Seleccionar las filas donde 'W' sea mayor que cero
# y de esas filas escoger los valores de las columna 'Y' y 'X'

#df[df['W']>0][['Y','Z']]
df.query('W>0')[['Y','Z']]

YZ
A0.9079690.503826
B-0.8480770.605965
D-0.9332370.955057
E2.6059670.683509

Para dos condiciones, puede usar | = or y & = and con paréntesis:

# Seleccionar las filas donde 'W' sea mayor que cero
# y tambien donde 'Y' sea mayor que 0.5

#df[(df['W']>0) & (df['Y'] > 0.5)]
df.query('W>0 and Y>0.5')

WYZ
A2.7068500.9079690.503826
E0.1907942.6059670.683509

Cambio de columna de Indexacion

Analicemos algunas características más de la indexación, incluido el restablecimiento del índice o el establecimiento de parametros.

df

WYZ
A2.7068500.9079690.503826
B0.651118-0.8480770.605965
C-2.0181680.528813-0.589001
D0.188695-0.9332370.955057
E0.1907942.6059670.683509
# Reinicializar el indice a su valor por defecto 0,1...n index
df = df.reset_index()
df

indexWYZ
0A2.7068500.9079690.503826
1B0.651118-0.8480770.605965
2C-2.0181680.528813-0.589001
3D0.188695-0.9332370.955057
4E0.1907942.6059670.683509
newind = 'CA NY WY OR CO'.split() # crear una lista con strings
newind
['CA', 'NY', 'WY', 'OR', 'CO']
# Agregar la lista creaada en el paso anterior al dataframe
df['States'] = newind
df

indexWYZStates
0A2.7068500.9079690.503826CA
1B0.651118-0.8480770.605965NY
2C-2.0181680.528813-0.589001WY
3D0.188695-0.9332370.955057OR
4E0.1907942.6059670.683509CO
# Redefinir la columna states como el indice
df.set_index('States')

indexWYZ
States
CAA2.7068500.9079690.503826
NYB0.651118-0.8480770.605965
WYC-2.0181680.528813-0.589001
ORD0.188695-0.9332370.955057
COE0.1907942.6059670.683509
# por que no queda establecido el indice?
df

indexWYZStates
0A2.7068500.9079690.503826CA
1B0.651118-0.8480770.605965NY
2C-2.0181680.528813-0.589001WY
3D0.188695-0.9332370.955057OR
4E0.1907942.6059670.683509CO
# para establecer el indice debe ser una funcion inplace
df.set_index('States',inplace=True)
#df = df.set_index('States') # otra forma de hacerlo
df

indexWYZ
States
CAA2.7068500.9079690.503826
NYB0.651118-0.8480770.605965
WYC-2.0181680.528813-0.589001
ORD0.188695-0.9332370.955057
COE0.1907942.6059670.683509

Groupby (Agrupacion por filas)

El método groupby le permite agrupar filas de datos y llamar a funciones agregadas

import pandas as pd
# Crear dataframe desde un diccionario
data = {'Company':['GOOG','GOOG','MSFT','MSFT','FB','FB','GOOG','MSFT','FB'],
       'Person':['Sam','Charlie','Amy','Vanessa','Carl','Sarah','John','Randy','David'],
       'Sales':[200,120,340,124,243,350,275,400,180]}
data
{'Company': ['GOOG', 'GOOG', 'MSFT', 'MSFT', 'FB', 'FB', 'GOOG', 'MSFT', 'FB'],
 'Person': ['Sam',
  'Charlie',
  'Amy',
  'Vanessa',
  'Carl',
  'Sarah',
  'John',
  'Randy',
  'David'],
 'Sales': [200, 120, 340, 124, 243, 350, 275, 400, 180]}
#conversion del diccionario a dataframe
df = pd.DataFrame(data)
df

CompanyPersonSales
0GOOGSam200
1GOOGCharlie120
2MSFTAmy340
3MSFTVanessa124
4FBCarl243
5FBSarah350
6GOOGJohn275
7MSFTRandy400
8FBDavid180

Se puede usar el método .groupby() para agrupar filas en función de un nombre de columna. Por ejemplo, vamos a agruparnos a partir de la Compañía. Esto creará un objeto DataFrameGroupBy:

#agrupar por Company
df.groupby('Company')
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x1279735e0>

Se puede grabar este objeto en una nueva variable:

by_comp = df.groupby("Company")

utilizar los métodos agregados del objeto:

# Promedio de ventas por company
by_comp.mean(numeric_only=True)

Sales
Company
FB257.666667
GOOG198.333333
MSFT288.000000
# agrupar por compañia y calcular el promedio por cada una
df.groupby('Company').mean(numeric_only=True)

Sales
Company
FB257.666667
GOOG198.333333
MSFT288.000000

Más ejemplos de métodos agregados:

# agrupar por compañia y calcular la desviacion estandard
by_comp.std(numeric_only=True)

Sales
Company
FB85.943780
GOOG77.513440
MSFT145.161978
# agrupar por compañia y calcular el minimo
by_comp.min()

PersonSales
Company
FBCarl180
GOOGCharlie120
MSFTAmy124
# agrupar por compañia y calcular el maximo
by_comp.max()

PersonSales
Company
FBSarah350
GOOGSam275
MSFTVanessa400
# agrupar por compañia y sumar los elementos que hay excluyendo los NaN
by_comp.count()

PersonSales
Company
FB33
GOOG33
MSFT33
# Una de las funciones mas usadas para descripcion estadistica de un dataframe
# Genera estadísticas descriptivas que resumen la tendencia central, la dispersión y la forma de la distribución de un conjunto de datos, excluyendo los valores `` NaN``.
# by_comp.describe(include = 'all') # incluir todo
by_comp.describe()

Sales
countmeanstdmin25%50%75%max
Company
FB3.0257.66666785.943780180.0211.5243.0296.5350.0
GOOG3.0198.33333377.513440120.0160.0200.0237.5275.0
MSFT3.0288.000000145.161978124.0232.0340.0370.0400.0
# Una de las funciones mas usadas para descripcion estadistica de un dataframe
# Genera estadísticas descriptivas que resumen la tendencia central, la dispersión y la forma de la distribución de un conjunto de datos, excluyendo los valores `` NaN``.
# Transponer la descripcion
by_comp.describe().transpose()

CompanyFBGOOGMSFT
Salescount3.0000003.0000003.000000
mean257.666667198.333333288.000000
std85.94378077.513440145.161978
min180.000000120.000000124.000000
25%211.500000160.000000232.000000
50%243.000000200.000000340.000000
75%296.500000237.500000370.000000
max350.000000275.000000400.000000
# Descripcion estadistica de los datos de la copmañia GOOG
by_comp.describe().transpose()['GOOG']
Sales  count      3.000000
       mean     198.333333
       std       77.513440
       min      120.000000
       25%      160.000000
       50%      200.000000
       75%      237.500000
       max      275.000000
Name: GOOG, dtype: float64

Pivot Tables

La funcionlidad “Pivot_table” es muy utilizada y popular en las conocidas “hojas de cálculo” tipo, OpenOffice, LibreOffice, Excel, Lotus, etc. Esta funcionalidad nos permite agrupar, ordenar, calcular datos y manejar datos de una forma muy similar a la que se hace con las hojas de cálculo. mas informacion

La principal función del “Pivot_table” son las agrupaciones de datos a las que se les suelen aplicar funciones matemáticas como sumatorios, promedios, etc

import seaborn as sns # importar la libreria seaborn
# cargar dataset del titanic
titanic = sns.load_dataset('titanic')
titanic.head()

survivedpclasssexagesibspparchfareembarkedclasswhoadult_maledeckembark_townalivealone
003male22.0107.2500SThirdmanTrueNaNSouthamptonnoFalse
111female38.01071.2833CFirstwomanFalseCCherbourgyesFalse
213female26.0007.9250SThirdwomanFalseNaNSouthamptonyesTrue
311female35.01053.1000SFirstwomanFalseCSouthamptonyesFalse
403male35.0008.0500SThirdmanTrueNaNSouthamptonnoTrue

Haciendo el Pivot table a mano para obtener el promedio de personas que sobrevivieron por genero

# 1. Agrupar por genero
# 2. Obtener los sobrevivientes
# 3. Calcular el promedio
titanic.groupby('sex')[['survived']].mean()

survived
sex
female0.742038
male0.188908

promedio de cuantos sobrevivieron por genero divididos por clase

# 1. Agrupar por genero y clase
# 2. Obtener los sobrevivientes
# 3. Calcular el promedio
# 4. Poner el resultado como una tabla (.unstack)
titanic.groupby(['sex', 'class'])['survived'].mean().unstack()

classFirstSecondThird
sex
female0.9680850.9210530.500000
male0.3688520.1574070.135447

Usando Pivot tables

titanic.pivot_table('survived', index='sex', columns='class')

classFirstSecondThird
sex
female0.9680850.9210530.500000
male0.3688520.1574070.135447
titanic.pivot_table('survived', index='sex', columns='class', margins=True)

classFirstSecondThirdAll
sex
female0.9680850.9210530.5000000.742038
male0.3688520.1574070.1354470.188908
All0.6296300.4728260.2423630.383838

Concatenar, Fusionar y Unir (Concatenating, Merging, Joining)

Hay 3 formas principales de combinar DataFrames: concatenar, fusionar y unir.

# DataFrames de ejemplo para concatenacion
import pandas as pd
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']},
                        index=[0, 1, 2, 3])
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                        'B': ['B4', 'B5', 'B6', 'B7'],
                        'C': ['C4', 'C5', 'C6', 'C7'],
                        'D': ['D4', 'D5', 'D6', 'D7']},
                         index=[4, 5, 6, 7]) 
df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
                        'B': ['B8', 'B9', 'B10', 'B11'],
                        'C': ['C8', 'C9', 'C10', 'C11'],
                        'D': ['D8', 'D9', 'D10', 'D11']},
                        index=[8, 9, 10, 11])
df1

ABCD
0A0B0C0D0
1A1B1C1D1
2A2B2C2D2
3A3B3C3D3
df2

ABCD
4A4B4C4D4
5A5B5C5D5
6A6B6C6D6
7A7B7C7D7
df3

ABCD
8A8B8C8D8
9A9B9C9D9
10A10B10C10D10
11A11B11C11D11

Concatenacion (Concatenation)

La concatenación básicamente combina DataFrames. Tenga en cuenta que las dimensiones deben coincidir a lo largo del eje con el que se está concatenando.

la concatenacion se hace con dataframes de diferentes indices

Puede usar .concat() y pasar una lista de DataFrames para concatenar juntos:

# Concatenar cada dateframe verticalmente,
# ya que coinciden los nombres de las columnas

pd.concat([df1,df2,df3], axis='index')

ABCD
0A0B0C0D0
1A1B1C1D1
2A2B2C2D2
3A3B3C3D3
4A4B4C4D4
5A5B5C5D5
6A6B6C6D6
7A7B7C7D7
8A8B8C8D8
9A9B9C9D9
10A10B10C10D10
11A11B11C11D11
#concatenar dataframe horizontalmente, 
# como no coinciden los index observar lo que ocurre

pd.concat([df1,df2,df3], axis='columns')

ABCDABCDABCD
0A0B0C0D0NaNNaNNaNNaNNaNNaNNaNNaN
1A1B1C1D1NaNNaNNaNNaNNaNNaNNaNNaN
2A2B2C2D2NaNNaNNaNNaNNaNNaNNaNNaN
3A3B3C3D3NaNNaNNaNNaNNaNNaNNaNNaN
4NaNNaNNaNNaNA4B4C4D4NaNNaNNaNNaN
5NaNNaNNaNNaNA5B5C5D5NaNNaNNaNNaN
6NaNNaNNaNNaNA6B6C6D6NaNNaNNaNNaN
7NaNNaNNaNNaNA7B7C7D7NaNNaNNaNNaN
8NaNNaNNaNNaNNaNNaNNaNNaNA8B8C8D8
9NaNNaNNaNNaNNaNNaNNaNNaNA9B9C9D9
10NaNNaNNaNNaNNaNNaNNaNNaNA10B10C10D10
11NaNNaNNaNNaNNaNNaNNaNNaNA11B11C11D11

Fusion (Merging)

La función merge() le permite fusionar DataFrames juntos utilizando una lógica similar a la combinación de Tablas SQL. Por ejemplo:

# DataFrames de ejemplo para merging
left = pd.DataFrame({
    'Producto': ['Arepas', 'Banano', 'Cafe'],
    'Tienda': [1, 2, 1],
    'Ventas': [100, 200, 50]
})
   
right = pd.DataFrame({
    'Producto': ['Arepas', 'Banano', 'Cafe'],
    'Tienda': [1, 2, 1],
    'Inventario': [50, 100, 75]
})    
left

ProductoTiendaVentas
0Arepas1100
1Banano2200
2Cafe150
right

ProductoTiendaInventario
0Arepas150
1Banano2100
2Cafe175
# how='inner' utilice la intersección de las claves de ambos marcos, similar a una combinación interna de SQL; 
# las keys son comunes
pd.merge(left,right,how='inner',on='Producto')

ProductoTienda_xVentasTienda_yInventario
0Arepas1100150
1Banano22002100
2Cafe150175

Un ejemplo mas complicado:

  • Natural join: para mantener solo las filas que coinciden con los marcos de datos, especifique el argumento how = ‘inner’.
  • Full outer join: para mantener todas las filas de ambos dataframe, especifique how = ‘OUTER’.
  • Left outer join: para incluir todas las filas de su dataframe x y solo aquellas de y que coincidan, especifique how=‘left’.
  • Right outer join: para incluir todas las filas de su dataframe y y solo aquellas de x que coincidan, especifique how=‘right’.

left = pd.DataFrame({
    'Producto': ['Arepas', 'Leche', 'Cafe'],
    'Tienda': [1, 2, 1],
    'Ventas': [100, 200, 50]
})
   
right = pd.DataFrame({
    'Producto': ['Arepas', 'Banano', 'Cafe'],
    'Tienda': [1, 2, 1],
    'Inventario': [50, 100, 75]
}) 
left

ProductoTiendaVentas
0Arepas1100
1Leche2200
2Cafe150
right

ProductoTiendaInventario
0Arepas150
1Banano2100
2Cafe175
# fusionando comparando las mismas claves que tengan comunes
pd.merge(left, right, on=['Producto'])

ProductoTienda_xVentasTienda_yInventario
0Arepas1100150
1Cafe150175
# fusionando totalmente las dos tablas con las claves
pd.merge(left, right, how='outer', on=['Producto'])

ProductoTienda_xVentasTienda_yInventario
0Arepas1.0100.01.050.0
1Leche2.0200.0NaNNaN
2Cafe1.050.01.075.0
3BananoNaNNaN2.0100.0
# fusionando usando las claves de la tabla right
pd.merge(left, right, how='right', on=['Producto'])

ProductoTienda_xVentasTienda_yInventario
0Arepas1.0100.0150
1BananoNaNNaN2100
2Cafe1.050.0175
# fusionando usando las claves de la tabla left
pd.merge(left, right, how='left', on=['Producto']) 

ProductoTienda_xVentasTienda_yInventario
0Arepas11001.050.0
1Leche2200NaNNaN
2Cafe1501.075.0

Datos Categoricos

  • La busqueda en datos categoricos es mucho mas rapida
  • Ocupan Menos memoria que si los datos estan como string
  • Se pueden tener datos categoricos Ordinales

Mas informacion de datos categoricos:

https://pandas.pydata.org/pandas-docs/stable/user_guide/categorical.html

Creacion

# Creacion de una serie de datos categoricos
cate = pd.Series(["manzana", "banano", "corozo", "manzana","pera"],
                 dtype="category")
cate
0    manzana
1     banano
2     corozo
3    manzana
4       pera
dtype: category
Categories (4, object): ['banano', 'corozo', 'manzana', 'pera']
cate.dtypes
CategoricalDtype(categories=['banano', 'corozo', 'manzana', 'pera'], ordered=False)
cate.describe()
count           5
unique          4
top       manzana
freq            2
dtype: object
# Creando primero los datos y luego convirtiendolos en categoricos
df_cate = pd.DataFrame({"Fruta":["manzana", "banano", "corozo", "manzana","pera"]})
df_cate

Fruta
0manzana
1banano
2corozo
3manzana
4pera
# Observar los tipos de datos en el data frame
df_cate.dtypes
Fruta    object
dtype: object
df_cate["Fruta2"] = df_cate["Fruta"].astype('category')
df_cate

FrutaFruta2
0manzanamanzana
1bananobanano
2corozocorozo
3manzanamanzana
4perapera
# Observar los tipos de datos en el dataframe
df_cate.dtypes
Fruta       object
Fruta2    category
dtype: object
# Crear los datos categoricos desde a declaracion de los datos
df_cate = pd.DataFrame({'A': list('abca'),
                        'B': list('bccd')},
                       dtype="category")
df_cate

AB
0ab
1bc
2cc
3ad
df_cate.dtypes
A    category
B    category
dtype: object
df_cate.describe()

AB
count44
unique33
topac
freq22

Categoricos Ordinales

# creacion de dataframe con datos
df_cate = pd.DataFrame({'A': list('abca'),
                        'B': list('bccd')})
df_cate

AB
0ab
1bc
2cc
3ad
df_cate.dtypes
A    object
B    object
dtype: object
# Definicion de los tipos de datos y que estan en orden
df_cate["A"] = pd.Categorical(df_cate['A'],
                              categories=['a','b','c','d'],
                              ordered=True)
df_cate

AB
0ab
1bc
2cc
3ad
df_cate["A"]
0    a
1    b
2    c
3    a
Name: A, dtype: category
Categories (4, object): ['a' < 'b' < 'c' < 'd']
# Los datos no tienen que ser strings para que sean categoricos
s = pd.Series([1, 2, 3, 1], dtype="category")
s
0    1
1    2
2    3
3    1
dtype: category
Categories (3, int64): [1, 2, 3]
s = s.cat.set_categories([2, 3, 1],
                         ordered=True)
s
0    1
1    2
2    3
3    1
dtype: category
Categories (3, int64): [2 < 3 < 1]

Correcion de tipos de datos (Casting)

Cuando se trabaja con datos, es posible que se encuentre con un DataFrame donde el tipo de datos de una columna no es la correcta. los tipos de datos son principalmente: numericos, categoricos nominales, categoricos ordinales, booleanos, fechas y tiempos, texto.

Se debe convertir los tipos de datos para que sean apropiados para el tipo de datos que representan. Por ejemplo, es posible que desee convertir una columna de strings que representan números en números enteros o flotantes. O puede tener una columna de números que representan fechas, pero que pandas no reconoce como fechas.

Nota: al convertir los datos a su forma correcta, normalmente hace que los DataFrames sean mucho más pequeños en la memoria, lo que los hace más eficientes de usar.

import seaborn as sns # importar la libreria seaborn
titanic = sns.load_dataset('titanic')
titanic.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 15 columns):
 #   Column       Non-Null Count  Dtype   
---  ------       --------------  -----   
 0   survived     891 non-null    int64   
 1   pclass       891 non-null    int64   
 2   sex          891 non-null    object  
 3   age          714 non-null    float64 
 4   sibsp        891 non-null    int64   
 5   parch        891 non-null    int64   
 6   fare         891 non-null    float64 
 7   embarked     889 non-null    object  
 8   class        891 non-null    category
 9   who          891 non-null    object  
 10  adult_male   891 non-null    bool    
 11  deck         203 non-null    category
 12  embark_town  889 non-null    object  
 13  alive        891 non-null    object  
 14  alone        891 non-null    bool    
dtypes: bool(2), category(2), float64(2), int64(4), object(5)
memory usage: 80.7+ KB
titanic.sample(5)

survivedpclasssexagesibspparchfareembarkedclasswhoadult_maledeckembark_townalivealone
18312male1.02139.0000SSecondchildFalseFSouthamptonyesFalse
63301maleNaN000.0000SFirstmanTrueNaNSouthamptonnoTrue
67503male18.0007.7750SThirdmanTrueNaNSouthamptonnoTrue
62213male20.01115.7417CThirdmanTrueNaNCherbourgyesFalse
12312female32.50013.0000SSecondwomanFalseESouthamptonyesTrue

Casting variables Categoricas nominales

# convertir la columna sex, embarked, who, embark_town en categoricas
cols_categoricas_nom = ["sex", "embarked", "who", "embark_town"]

# ver los datos unicos de las columnas_categoricas_nom
for columna in cols_categoricas_nom:
  print(f"Valores únicos en {columna}: {titanic[columna].unique()}")
Valores únicos en sex: ['male' 'female']
Valores únicos en embarked: ['S' 'C' 'Q' nan]
Valores únicos en who: ['man' 'woman' 'child']
Valores únicos en embark_town: ['Southampton' 'Cherbourg' 'Queenstown' nan]
titanic[cols_categoricas_nom] = titanic[cols_categoricas_nom].astype("category")

# ver los datos unicos de las columnas_categoricas_nom
for columna in cols_categoricas_nom:
  print(f"Valores únicos en {columna}: {titanic[columna].unique()}")
Valores únicos en sex: ['male', 'female']
Categories (2, object): ['female', 'male']
Valores únicos en embarked: ['S', 'C', 'Q', NaN]
Categories (3, object): ['C', 'Q', 'S']
Valores únicos en who: ['man', 'woman', 'child']
Categories (3, object): ['child', 'man', 'woman']
Valores únicos en embark_town: ['Southampton', 'Cherbourg', 'Queenstown', NaN]
Categories (3, object): ['Cherbourg', 'Queenstown', 'Southampton']

Casting variables Categoricas Ordinales

cols_categoricas_ord = ["pclass", "deck"]

for columna in cols_categoricas_ord:
  print(f"Valores únicos en {columna}: {titanic[columna].unique()}")
Valores únicos en pclass: [3 1 2]
Valores únicos en deck: [NaN, 'C', 'E', 'G', 'D', 'A', 'B', 'F']
Categories (7, object): ['A', 'B', 'C', 'D', 'E', 'F', 'G']
titanic["pclass"] = pd.Categorical(titanic["pclass"],
                                   categories=[3, 2, 1],
                                   ordered=True)
titanic["deck"] = pd.Categorical(titanic["deck"],
                                 categories=list("ABCDEFG"),
                                 ordered=True)
for columna in cols_categoricas_ord:
  print(f"Valores únicos en {columna}: {titanic[columna].unique()}")
Valores únicos en pclass: [3, 1, 2]
Categories (3, int64): [3 < 2 < 1]
Valores únicos en deck: [NaN, 'C', 'E', 'G', 'D', 'A', 'B', 'F']
Categories (7, object): ['A' < 'B' < 'C' < 'D' < 'E' < 'F' < 'G']

Casting variables booleanas

columnas_bool = ["alive", "alone", "survived"]

titanic[columnas_bool] = titanic[columnas_bool].astype("bool")

Resulado Casting

titanic.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 15 columns):
 #   Column       Non-Null Count  Dtype   
---  ------       --------------  -----   
 0   survived     891 non-null    bool    
 1   pclass       891 non-null    category
 2   sex          891 non-null    category
 3   age          714 non-null    float64 
 4   sibsp        891 non-null    int64   
 5   parch        891 non-null    int64   
 6   fare         891 non-null    float64 
 7   embarked     889 non-null    category
 8   class        891 non-null    category
 9   who          891 non-null    category
 10  adult_male   891 non-null    bool    
 11  deck         203 non-null    category
 12  embark_town  889 non-null    category
 13  alive        891 non-null    bool    
 14  alone        891 non-null    bool    
dtypes: bool(4), category(7), float64(2), int64(2)
memory usage: 38.7 KB

Datos Faltantes (Missing data)

Métodos para Manejar datos faltantes en pandas:

# Declaracion de data frame con algunos datos faltantes
# NaN = Not a Number
df = pd.DataFrame({'A':[1,2,np.nan],
                  'B':[5,np.nan,np.nan],
                  'C':[1,2,3]})
df

ABC
01.05.01
12.0NaN2
2NaNNaN3

Detectar si Faltan datos

# verificar cuales valores son NaN o nulos (Null)
df.isna()

ABC
0FalseFalseFalse
1FalseTrueFalse
2TrueTrueFalse
# Verificar si hay datos faltantes por columna
df.isna().any()
A     True
B     True
C    False
dtype: bool

Numero de datos faltantes

Calcular el numero de datos nulos que hay por columna

# Numero de datos faltantes por columna
df.isna().sum()
A    1
B    2
C    0
dtype: int64

Eliminar datos Faltantes

# Eliminar todas las filas que tengan datos faltantes
df.dropna(axis='index') # cuando son filas no es neceario escribir axis=0

ABC
01.05.01
# Eliminar todas las columnas que tengan datos faltantes
df.dropna(axis='columns')

C
01
12
23
# eliminar las filas que tengas 2 o mas valores NaN
df.dropna(thresh=2)

ABC
01.05.01
12.0NaN2

Reemplazar los datos faltantes

# Llenar los datos faltantes con el dato que nos interese
df.fillna(value='Llenar Valores') # llenar los espacios con un string
                              # puede ser una palabra, numero , etc

ABC
01.05.01
12.0Llenar Valores2
2Llenar ValoresLlenar Valores3
# Llenar los datos faltantes con el dato que nos interese
df.fillna(value=99) # llenar los espacios con un numero

ABC
01.05.01
12.099.02
299.099.03
# Llenar los datos faltantes con el promedio de esa columna
df['A'].fillna(value=df['A'].mean())
0    1.0
1    2.0
2    1.5
Name: A, dtype: float64
# Llenar los datos faltantes con el promedio de cada columna
df.fillna(value=df.mean())

ABC
01.05.01
12.05.02
21.55.03

Datos unicos (Unique Values)

import pandas as pd
# crear un dataframe
df = pd.DataFrame({'col1':[1,2,3,4],
                   'col2':[444,555,666,444],
                   'col3':['abc','def','ghi','xyz']})
df.head() # solamente mostrar los primeros elementos del dataframe

col1col2col3
01444abc
12555def
23666ghi
34444xyz
# valores unicos de la columna col2
df['col2'].unique()
array([444, 555, 666])
# Numero de valores unicos en el dataframe
df['col2'].nunique()
3
# contar cuanto se repiten cada uno de los valores
df['col2'].value_counts()
444    2
555    1
666    1
Name: col2, dtype: int64

Datos Duplicados

Se puede borrar los registros que son exactamente iguales en todos los valores de las columnas

import pandas as pd
datos = {'nombre': ['Jaime', 'Juan', 'Roberto', 'Juan'],
         'edad': [18, 20, 22, 20],
         'trabajo': ['Asistente', 'Manager', 'Cientifico', 'Manager']}
df_dup = pd.DataFrame(datos)
df_dup

nombreedadtrabajo
0Jaime18Asistente
1Juan20Manager
2Roberto22Cientifico
3Juan20Manager
# Metodo para detectar los datos duplicados
# me sirve para ver si existen registros duplicados
df_dup.duplicated()
0    False
1    False
2    False
3     True
dtype: bool
# Contar cuantos datos duplicados existen
df_dup.duplicated().sum()
1
# Para remover los datos duplicados
df_dup.drop_duplicates()

nombreedadtrabajo
0Jaime18Asistente
1Juan20Manager
2Roberto22Cientifico
# El metodo drop_duplicates entrega el data frame sin duplicados
# Pero la funcion no es inplace, osea que el dataframe original sigue igual
df_dup

nombreedadtrabajo
0Jaime18Asistente
1Juan20Manager
2Roberto22Cientifico
3Juan20Manager
df_dup.drop_duplicates(inplace=True)
df_dup

nombreedadtrabajo
0Jaime18Asistente
1Juan20Manager
2Roberto22Cientifico

Duplicados por Columna

Se pueden borrar los valores que se repitan solamente verificando la columna

frame_datos = {'nombre': ['Jaime', 'Juan', 'Roberto', 'Juan'],
               'edad': [18, 20, 22, 21],
              'trabajo': ['Asistente', 'Manager', 'Cientifico', 'Profesor']}
df_dup = pd.DataFrame(frame_datos)
df_dup

nombreedadtrabajo
0Jaime18Asistente
1Juan20Manager
2Roberto22Cientifico
3Juan21Profesor

el valor de jason esta duplicado en la columna name

# recordar que estas funciones no son inplace
df_dup.drop_duplicates(['nombre'])

nombreedadtrabajo
0Jaime18Asistente
1Juan20Manager
2Roberto22Cientifico

Outliers

Una de las formas de eliminar los outliers es identificando cual sera el rango en el que queremos nuestros datos y limitar los datos entre ese rango

import seaborn as sns # importar la libreria seaborn
# cargar dataset del titanic
titanic = sns.load_dataset('titanic')
titanic.head()

survivedpclasssexagesibspparchfareembarkedclasswhoadult_maledeckembark_townalivealone
003male22.0107.2500SThirdmanTrueNaNSouthamptonnoFalse
111female38.01071.2833CFirstwomanFalseCCherbourgyesFalse
213female26.0007.9250SThirdwomanFalseNaNSouthamptonyesTrue
311female35.01053.1000SFirstwomanFalseCSouthamptonyesFalse
403male35.0008.0500SThirdmanTrueNaNSouthamptonnoTrue
edad = titanic['age']
edad
0      22.0
1      38.0
2      26.0
3      35.0
4      35.0
5       NaN
6      54.0
7       2.0
8      27.0
9      14.0
10      4.0
11     58.0
12     20.0
13     39.0
14     14.0
15     55.0
16      2.0
17      NaN
18     31.0
19      NaN
20     35.0
21     34.0
22     15.0
23     28.0
24      8.0
25     38.0
26      NaN
27     19.0
28      NaN
29      NaN
       ... 
861    21.0
862    48.0
863     NaN
864    24.0
865    42.0
866    27.0
867    31.0
868     NaN
869     4.0
870    26.0
871    47.0
872    33.0
873    47.0
874    28.0
875    15.0
876    20.0
877    19.0
878     NaN
879    56.0
880    25.0
881    33.0
882    22.0
883    28.0
884    25.0
885    39.0
886    27.0
887    19.0
888     NaN
889    26.0
890    32.0
Name: age, Length: 891, dtype: float64
# Cual es la edad maxima
edad.max()
80.0
# Cual es la edad Minima
edad.min()
0.42

Solo por hacer el ejercicio se delimitaran las edades entre 1 y 70 años

esto se puede hacer con el metodo .clip(lower = Valor mas bajo, upper = valor mas alto)

edad = edad.clip(lower=1,upper = 70)
edad.max()
70.0
edad.min()
1.0

Tablas de Contingencia (two way tables)

# Crear Datos
raw_data = {'regiment': ['Nighthawks', 'Nighthawks', 'Nighthawks', 'Nighthawks', 'Dragoons', 'Dragoons', 'Dragoons', 'Dragoons', 'Scouts', 'Scouts', 'Scouts', 'Scouts'], 
        'company': ['infantry', 'infantry', 'cavalry', 'cavalry', 'infantry', 'infantry', 'cavalry', 'cavalry','infantry', 'infantry', 'cavalry', 'cavalry'], 
        'experience': ['veteran', 'rookie', 'veteran', 'rookie', 'veteran', 'rookie', 'veteran', 'rookie','veteran', 'rookie', 'veteran', 'rookie'],
        'name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze', 'Jacon', 'Ryaner', 'Sone', 'Sloan', 'Piger', 'Riani', 'Ali'], 
        'preTestScore': [4, 24, 31, 2, 3, 4, 24, 31, 2, 3, 2, 3],
        'postTestScore': [25, 94, 57, 62, 70, 25, 94, 57, 62, 70, 62, 70]}
df = pd.DataFrame(raw_data, columns = ['regiment', 'company', 'experience', 'name', 'preTestScore', 'postTestScore'])
df

regimentcompanyexperiencenamepreTestScorepostTestScore
0NighthawksinfantryveteranMiller425
1NighthawksinfantryrookieJacobson2494
2NighthawkscavalryveteranAli3157
3NighthawkscavalryrookieMilner262
4DragoonsinfantryveteranCooze370
5DragoonsinfantryrookieJacon425
6DragoonscavalryveteranRyaner2494
7DragoonscavalryrookieSone3157
8ScoutsinfantryveteranSloan262
9ScoutsinfantryrookiePiger370
10ScoutscavalryveteranRiani262
11ScoutscavalryrookieAli370
# Tabla de contingencia por compañía y regimiento
pd.crosstab(df['regiment'], df['company'], margins=True)

companycavalryinfantryAll
regiment
Dragoons224
Nighthawks224
Scouts224
All6612
# Tabla de contingencia de compañia y experiencia por regimiento
pd.crosstab([df['company'], df['experience']], df['regiment'],  margins=True)

regimentDragoonsNighthawksScoutsAll
companyexperience
cavalryrookie1113
veteran1113
infantryrookie1113
veteran1113
All44412

Metodos y Funciones en Pandas

Todos los metodos de los dataframe de pandas se pueden encontrar en:

http://pandas.pydata.org/pandas-docs/stable/reference/frame.html

import pandas as pd
# crear un dataframe
df = pd.DataFrame({'col1':[1,2,3,4],
                   'col2':[444,555,666,444],
                   'col3':['mama   ','  papa','   HIJO  ','HiJa']})
df.head() # solamente mostrar los primeros elementos del dataframe

col1col2col3
01444mama
12555papa
23666HIJO
34444HiJa

Metodos Basicos Pandas

Ejemplos simples de los metodos de los dataframe de pandas

Para informacion completa de los metodos de computacion y estadisticos ver:

http://pandas.pydata.org/pandas-docs/stable/reference/frame.html#computations-descriptive-stats

# Suma total de cada Columna, si es categorico no lo suma
df.sum()
col1                            10
col2                          2109
col3    mama     papa   HIJO  HiJa
dtype: object
# Metodo en una sola columna
df['col1'].sum()
10
# Metodo en varias columnas
df[['col1','col2']].sum()
col1      10
col2    2109
dtype: int64
# Valor Minimo cada Columna
df.min()
col1            1
col2          444
col3       HIJO  
dtype: object
# Valor Maximo cada Columna
df.max()
col1          4
col2        666
col3    mama   
dtype: object

Metodos de Informacion General

# Cargar la base de datos 'mpg' de la libreria seaborn
import seaborn as sns

# los datos se cargan en un dataframe
data = sns.load_dataset('mpg')
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 398 entries, 0 to 397
Data columns (total 9 columns):
mpg             398 non-null float64
cylinders       398 non-null int64
displacement    398 non-null float64
horsepower      392 non-null float64
weight          398 non-null int64
acceleration    398 non-null float64
model_year      398 non-null int64
origin          398 non-null object
name            398 non-null object
dtypes: float64(4), int64(3), object(2)
memory usage: 28.1+ KB
data.head()

mpgcylindersdisplacementhorsepowerweightaccelerationmodel_yearoriginname
018.08307.0130.0350412.070usachevrolet chevelle malibu
115.08350.0165.0369311.570usabuick skylark 320
218.08318.0150.0343611.070usaplymouth satellite
316.08304.0150.0343312.070usaamc rebel sst
417.08302.0140.0344910.570usaford torino
data.describe() # ver datos estadisticos de las columnas numericas

mpgcylindersdisplacementhorsepowerweightaccelerationmodel_year
count398.000000398.000000398.000000392.000000398.000000398.000000398.000000
mean23.5145735.454774193.425879104.4693882970.42462315.56809076.010050
std7.8159841.701004104.26983838.491160846.8417742.7576893.697627
min9.0000003.00000068.00000046.0000001613.0000008.00000070.000000
25%17.5000004.000000104.25000075.0000002223.75000013.82500073.000000
50%23.0000004.000000148.50000093.5000002803.50000015.50000076.000000
75%29.0000008.000000262.000000126.0000003608.00000017.17500079.000000
max46.6000008.000000455.000000230.0000005140.00000024.80000082.000000
data.describe(include = 'all') # ver todos los datos incluidos los categoricos

mpgcylindersdisplacementhorsepowerweightaccelerationmodel_yearoriginname
count398.000000398.000000398.000000392.000000398.000000398.000000398.000000398398
uniqueNaNNaNNaNNaNNaNNaNNaN3305
topNaNNaNNaNNaNNaNNaNNaNusaford pinto
freqNaNNaNNaNNaNNaNNaNNaN2496
mean23.5145735.454774193.425879104.4693882970.42462315.56809076.010050NaNNaN
std7.8159841.701004104.26983838.491160846.8417742.7576893.697627NaNNaN
min9.0000003.00000068.00000046.0000001613.0000008.00000070.000000NaNNaN
25%17.5000004.000000104.25000075.0000002223.75000013.82500073.000000NaNNaN
50%23.0000004.000000148.50000093.5000002803.50000015.50000076.000000NaNNaN
75%29.0000008.000000262.000000126.0000003608.00000017.17500079.000000NaNNaN
max46.6000008.000000455.000000230.0000005140.00000024.80000082.000000NaNNaN
# Descripcion de una sola columna
data['cylinders'].describe()
count    398.000000
mean       5.454774
std        1.701004
min        3.000000
25%        4.000000
50%        4.000000
75%        8.000000
max        8.000000
Name: cylinders, dtype: float64
data['mpg'].describe()
count    398.000000
mean      23.514573
std        7.815984
min        9.000000
25%       17.500000
50%       23.000000
75%       29.000000
max       46.600000
Name: mpg, dtype: float64
data['cylinders'].dtypes
dtype('int64')

Estadistica Descriptiva

Metodos de Estadistica Descriptiva, de medida central, simetria, momentos, etc. para mas informacion: http://pandas.pydata.org/pandas-docs/stable/reference/frame.html#computations-descriptive-stats

Los calculos de las medidas estadisticas se hacen siempre en columnas, es algo predeterminado, si se quiere hacer por filas, se debe especificar dentro de los metodos el parametro axis=1.

Ejemplo:

  • Calculo de la media por columnas (predeterminado) = df.mean()
  • Calculo de la media por filas = df.mean(axis='columns')

Esto funciona con los otros tipos de medidas estadisticas

# Se tomara la columna 'mpg' para realizar los calculos
X = data['mpg']
type(X)
pandas.core.series.Series

Medidas de centralizacion

estas funciones se aplican sobre un dataframe de pandas

Media

# Media Aritmetica
X.mean()
23.514572864321615
# Media aritmetica en un dataframe
data.mean()
mpg               23.514573
cylinders          5.454774
displacement     193.425879
horsepower       104.469388
weight          2970.424623
acceleration      15.568090
model_year        76.010050
dtype: float64

Mediana

# Mediana
X.median()
23.0
# Mediana en un dataframe
data.median()
mpg               23.0
cylinders          4.0
displacement     148.5
horsepower        93.5
weight          2803.5
acceleration      15.5
model_year        76.0
dtype: float64

Maximo y Minimo

# Maximo
X.max()
46.6
# Maximo en un dataframe
data.max()
mpg                         46.6
cylinders                      8
displacement                 455
horsepower                   230
weight                      5140
acceleration                24.8
model_year                    82
origin                       usa
name            vw rabbit custom
dtype: object
# Minimo
X.min()
9.0
# Minimo en un dataframe
data.min()
mpg                                   9
cylinders                             3
displacement                         68
horsepower                           46
weight                             1613
acceleration                          8
model_year                           70
origin                           europe
name            amc ambassador brougham
dtype: object

Moda

# Moda
X.mode()
0    13.0
dtype: float64
# Moda en un dataframe
data.mode()

mpgcylindersdisplacementhorsepowerweightaccelerationmodel_yearoriginname
013.04.097.0150.0198514.573.0usaford pinto
1NaNNaNNaNNaN2130NaNNaNNaNNaN

Cuartiles

# Valores de los cuartiles
X.quantile([0, .25, .5, .75, 1])
0.00     9.0
0.25    17.5
0.50    23.0
0.75    29.0
1.00    46.6
Name: mpg, dtype: float64
# Valores de los cuartiles en un dataframe
data.quantile([0, .25, .5, .75, 1])

mpgcylindersdisplacementhorsepowerweightaccelerationmodel_year
0.009.03.068.0046.01613.008.00070.0
0.2517.54.0104.2575.02223.7513.82573.0
0.5023.04.0148.5093.52803.5015.50076.0
0.7529.08.0262.00126.03608.0017.17579.0
1.0046.68.0455.00230.05140.0024.80082.0

Medidas de dispersion

Varianza

# Varianza
X.var() #unbiased Normalized by N-1 by default.
61.089610774274405
# Varianza en un dataframe
data.var()
mpg                 61.089611
cylinders            2.893415
displacement     10872.199152
horsepower        1481.569393
weight          717140.990526
acceleration         7.604848
model_year          13.672443
dtype: float64

Desviacion Estandard

# Desviacion tipica o desviacion estandard
X.std()
7.815984312565782
# Desviacion tipica o desviacion estandard en un dataframe
data.std()
mpg               7.815984
cylinders         1.701004
displacement    104.269838
horsepower       38.491160
weight          846.841774
acceleration      2.757689
model_year        3.697627
dtype: float64

Coeficiente de Variacion

# Coeficiente de Variacion
X.std()/X.mean()
0.3323889554645019

Medidas de Asimetria

Asimetria de Fisher (skewness)

La asimetría es la medida que indica la simetría de la distribución de una variable respecto a la media aritmética, sin necesidad de hacer la representación gráfica. Los coeficientes de asimetría indican si hay el mismo número de elementos a izquierda y derecha de la media.

Existen tres tipos de curva de distribución según su asimetría:

  • Asimetría negativa: la cola de la distribución se alarga para valores inferiores a la media.
  • Simétrica: hay el mismo número de elementos a izquierda y derecha de la media. En este caso, coinciden la media, la mediana y la moda. La distribución se adapta a la forma de la campana de Gauss, o distribución normal.
  • Asimetría positiva: la cola de la distribución se alarga para valores superiores a la media.

#unbiased skew, Normalized by N-1
X.skew() 
0.45706634399491913
#unbiased skew, Normalized by N-1 en un dataframe
data.skew()
mpg             0.457066
cylinders       0.526922
displacement    0.719645
horsepower      1.087326
weight          0.531063
acceleration    0.278777
model_year      0.011535
dtype: float64

Curtosis

Esta medida determina el grado de concentración que presentan los valores en la región central de la distribución. Por medio del Coeficiente de Curtosis, podemos identificar si existe una gran concentración de valores (Leptocúrtica), una concentración normal (Mesocúrtica) ó una baja concentración (Platicúrtica).

# unbiased kurtosis over requested axis using Fisher's definition
X.kurtosis()
-0.5107812652123154
# unbiased kurtosis over requested axis using Fisher's definition
# en un dataframe
data.kurtosis()
mpg            -0.510781
cylinders      -1.376662
displacement   -0.746597
horsepower      0.696947
weight         -0.785529
acceleration    0.419497
model_year     -1.181232
dtype: float64

Covarianza

Entre Series

s1 = pd.Series(np.random.randn(1000))
s2 = pd.Series(np.random.randn(1000))
s1.cov(s2)
-0.028354705528775087
# Numpy
np.cov(s1,s2)
array([[ 1.09020966, -0.02835471],
       [-0.02835471,  1.07417272]])

Dataframe

frame = pd.DataFrame(np.random.randn(1000, 5),columns=['a', 'b', 'c', 'd', 'e'])
frame.head()

abcde
00.5768281.814651-0.261503-0.2546970.974428
10.0301710.6058640.079012-0.1725243.052445
2-0.842097-0.3517250.6285910.878268-0.055329
3-0.2731580.049033-0.3019810.562631-1.241831
4-0.3050870.4744970.648280-0.0263150.792715
frame.cov()

abcde
a1.0765750.000666-0.039799-0.002462-0.043501
b0.0006661.016370-0.015872-0.002416-0.021047
c-0.039799-0.0158721.036459-0.058312-0.057863
d-0.002462-0.002416-0.0583121.0006400.004340
e-0.043501-0.021047-0.0578630.0043400.952529

Correlacion

Metodos:

  • pearson (predeterminado)
  • kendall
  • spearman
#  Creacion de dataframe con datos aleatorios
frame = pd.DataFrame(np.random.randn(1000, 5),
                     columns=['a', 'b', 'c', 'd', 'e'])
frame.head()                     

abcde
00.3026651.693723-1.706086-1.159119-0.134841
10.3905280.1669050.1845020.8077060.072960
20.6387870.329646-0.497104-0.754070-0.943406
30.484752-0.1167731.9017550.2381271.996652
4-0.9932630.196800-1.1366450.0003661.025984

Entre Series

frame['a'].corr(frame['b']) # Pearson que es el predeterminado
-0.052592953776030495
frame['a'].corr(frame['b'], method='spearman') # Metodo spearman
-0.04775690375690376
frame['a'].corr(frame['b'], method='kendall') # Metodo Kendall
-0.03213613613613614
# Con Numpy se realiza el coefficiente de Pearson
# realiza la correlacion entre dos vectores
np.corrcoef(frame['a'],frame['b'])
array([[ 1.        , -0.05259295],
       [-0.05259295,  1.        ]])

Dataframe

frame.corr()

abcde
a1.000000-0.052593-0.0391700.001333-0.001645
b-0.0525931.0000000.0844880.0072180.009969
c-0.0391700.0844881.0000000.0801680.006809
d0.0013330.0072180.0801681.000000-0.039776
e-0.0016450.0099690.006809-0.0397761.000000
# con Numpy
np.corrcoef(frame)
array([[ 1.        , -0.58501996,  0.55616525, ...,  0.26806025,
        -0.35940809, -0.00452158],
       [-0.58501996,  1.        , -0.3400534 , ...,  0.11257458,
        -0.37590609, -0.58877942],
       [ 0.55616525, -0.3400534 ,  1.        , ...,  0.70442968,
         0.13326316, -0.19220235],
       ...,
       [ 0.26806025,  0.11257458,  0.70442968, ...,  1.        ,
         0.19271014, -0.79265039],
       [-0.35940809, -0.37590609,  0.13326316, ...,  0.19271014,
         1.        ,  0.14871875],
       [-0.00452158, -0.58877942, -0.19220235, ..., -0.79265039,
         0.14871875,  1.        ]])

Funciones Agregadas

Para aplicar una o mas funciones en cada columna de los dataframe

df.agg(['sum', 'min'])

col1col2col3
sum102109mama papa HIJO HiJa
min1444HIJO
# Aplicar los metodos en columnas especificas
df[['col1','col2']].agg(['sum', 'min'])

col1col2
sum102109
min1444

Aplicando Funciones a cada elemento

#definicion de funcion
def times2(x:float)->float:
    return x*2
# es mas o menos lo que hace la funcion map
# aplicar la funcion times2 a cada elemento de la col1 de dataframe df
df['col1'].apply(times2)
0    2
1    4
2    6
3    8
Name: col1, dtype: int64
df['col3'].apply(len) #longitud de cada uno de los datos de la col3
0    7
1    6
2    9
3    4
Name: col3, dtype: int64
df['col1'].sum() #sumatoria total de los elementos de la col1
10

(Sorting) Ordenar un DataFrame:

df

col1col2col3
01444mama
12555papa
23666HIJO
34444HiJa
# ordenar el dataframe de menor a mayor basado en col2
df.sort_values(by='col2') #inplace=False por default

col1col2col3
01444mama
34444HiJa
12555papa
23666HIJO
df.sort_values(by='col2',ascending=False)

col1col2col3
23666HIJO
12555papa
01444mama
34444HiJa

Metodos de strings

Los metodos de los strings se pueden usar en pandas de forma vectorizada

https://pandas.pydata.org/pandas-docs/stable/getting_started/basics.html#vectorized-string-methods

Los metodos vectorizados de los strings son:

https://pandas.pydata.org/pandas-docs/stable/user_guide/text.html#text-string-methods

Nota: Recordar que la mayoria de los metodos NO son inplace

df

col1col2col3
01444mama
12555papa
23666HIJO
34444HiJa
# Estos Metodos solo funcionan por columna (Series)
# se puede verificar el error
# df.str.lower()

Algunos ejemplos de metodos en strings en las columnas

# convertir strings en minuscula
df['col3'].str.lower()
0      mama   
1         papa
2       hijo  
3         hija
Name: col3, dtype: object
# convertir strings en Mayuscula
df['col3'].str.upper()
0      MAMA   
1         PAPA
2       HIJO  
3         HIJA
Name: col3, dtype: object
# Eliminar los espacios de los strings
df['col3'].str.strip()
0    mama
1    papa
2    HIJO
3    HiJa
Name: col3, dtype: object

Transformacion de Variables

  • Crear variables Dummy: convertir de categoría a númerica
  • Discretización o Binning: convertir de número a categoría

Columnas Dummy

Convertir variables categoricas a numericas

# crear datos categoricos
raw_data = {'first_name': ['Jason', 'Molly', 'Tina', 'Jake', 'Amy'], 
        'last_name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze'], 
        'sex': ['male', 'female', 'male', 'female', 'female']}
df = pd.DataFrame(raw_data, columns = ['first_name', 'last_name', 'sex'])
df

first_namelast_namesex
0JasonMillermale
1MollyJacobsonfemale
2TinaAlimale
3JakeMilnerfemale
4AmyCoozefemale
# Crear un set de variables dummy para la columna sex
df_sex = pd.get_dummies(df['sex'])
df_sex

femalemale
001
110
201
310
410
# unir los dos dataframes
df_new = df.join(df_sex)
df_new

first_namelast_namesexfemalemale
0JasonMillermale01
1MollyJacobsonfemale10
2TinaAlimale01
3JakeMilnerfemale10
4AmyCoozefemale10

Discretización o Binning

Conversion de Numerica a Categorica

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.cut.html

# dividir los datos en 3 rangos iguales (categorias)

pd.cut(np.array([3.5, 2.8, 1, 5, 3, 4, 0, 4.4, 2, 3]), 3)
[(3.333, 5.0], (1.667, 3.333], (-0.005, 1.667], (3.333, 5.0], (1.667, 3.333], (3.333, 5.0], (-0.005, 1.667], (3.333, 5.0], (1.667, 3.333], (1.667, 3.333]]
Categories (3, interval[float64]): [(-0.005, 1.667] < (1.667, 3.333] < (3.333, 5.0]]
# Asignar etiquetas ordenadas
pd.cut(np.array([3.5, 2.8, 1, 5, 3, 4,0, 4.4, 2, 3]),
       3, labels=["Malo", "Regular", "Bien"])
[Bien, Regular, Malo, Bien, Regular, Bien, Malo, Bien, Regular, Regular]
Categories (3, object): [Malo < Regular < Bien]
pd.cut(np.array([2, 4 , 10 , 35 , 25 , 60 , 23, 14]),
       3, labels=["Niño", "Adolescente", "Adulto"])
[Niño, Niño, Niño, Adolescente, Adolescente, Adulto, Adolescente, Niño]
Categories (3, object): [Niño < Adolescente < Adulto]

Leer y guardar Datos (Data Input and Output)

Pandas puede leer una variedad de tipos de archivos usando sus métodos pd.read_ mas informacion

  • CSV
  • Parquet (Formato recomendado)
  • Excel
  • Json
  • Html
  • SQL

Nota: estos se ejemplos se hacen con archivos previamente creados para la demostracion

CSV File (comma-separated values)

Este es un formato muy común para compartir datos. Los archivos CSV son archivos de texto, sin formato, que usan comas para separar filas. Sus desventajas son que no especifican tipos de datos, no admiten datos faltantes, entre otros.

No es un formato ideal para compartir datos.

CSV Input

# Leer archivos separados por comas, extension .csv
df_supermarket_csv = pd.read_csv('supermarkets.csv')
df_supermarket_csv

IDAddressCityStateCountryNameEmployees
013666 21st StSan FranciscoCA 94114USAMadeira8
12735 Dolores StSan FranciscoCA 94119USABready Shop15
23332 Hill StSan FranciscoCalifornia 94114USASuper River25
343995 23rd StSan FranciscoCA 94114USABen's Shop10
451056 Sanchez StSan FranciscoCaliforniaUSASanchez12
56551 Alvarado StSan FranciscoCA 94114USARichvalley20

CSV Output

# Grabar el dataframe como archivo separado por comas
df_supermarket_csv.to_csv('example_out.csv',index=False)

Parquet

Este es un formato de archivo binario de columna que es muy bueno para compartir datos. Es muy eficiente en el espacio y el tiempo de lectura.

Es el formato recomendado para compartir datos.

Para poder usarlo con pandas 1.5.3 es necesario instalar la libreria pyarrow

pip install pyarrow

Con la nueva version de pandas 2.x.x ya no es necesario instalar la libreria pyarrow

Parquet Input

# Leer archivos separados por comas, extension .csv
df_supermarket_parquet = pd.read_parquet('supermarkets.parquet')
df_supermarket_parquet

IDAddressCityStateCountryNameEmployees
013666 21st StSan FranciscoCA 94114USAMadeira8
12735 Dolores StSan FranciscoCA 94119USABready Shop15
23332 Hill StSan FranciscoCalifornia 94114USASuper River25
343995 23rd StSan FranciscoCA 94114USABen's Shop10
451056 Sanchez StSan FranciscoCaliforniaUSASanchez12
56551 Alvarado StSan FranciscoCA 94114USARichvalley20

Parquet Output

# Grabar el dataframe como archivo parquet
df_supermarket_parquet.to_parquet('example_out.parquet')

Archivo de texto separado por otro caracter

# este archivo los valores estan separados por ;
df_supermarket = pd.read_csv("supermarkets-semi-colons.txt",sep=';')
df_supermarket

IDAddressCityStateCountryNameEmployees
013666 21st StSan FranciscoCA 94114USAMadeira8
12735 Dolores StSan FranciscoCA 94119USABready Shop15
23332 Hill StSan FranciscoCalifornia 94114USASuper River25
343995 23rd StSan FranciscoCA 94114USABen's Shop10
451056 Sanchez StSan FranciscoCaliforniaUSASanchez12
56551 Alvarado StSan FranciscoCA 94114USARichvalley20

Excel

Pandas puede leer y escribir archivos de Excel, tenga en cuenta que esto solo importa datos. No fórmulas o imágenes, que tengan imágenes o macros pueden hacer que este método read_excel se bloquee.

Excel Input

# leer un archivo de excel
df2 = pd.read_excel("supermarkets.xlsx",sheet_name=0) #leer la primera hoja del archivo
df2

IDAddressCityStateCountrySupermarket NameNumber of Employees
013666 21st StSan FranciscoCA 94114USAMadeira8
12735 Dolores StSan FranciscoCA 94119USABready Shop15
23332 Hill StSan FranciscoCalifornia 94114USASuper River25
343995 23rd StSan FranciscoCA 94114USABen's Shop10
451056 Sanchez StSan FranciscoCaliforniaUSASanchez12
56551 Alvarado StSan FranciscoCA 94114USARichvalley20

Excel Output

df2.to_excel('Excel_Sample_out.xlsx',sheet_name='Hoja1')

JSON

JSON (JavaScript Object Notation - Notación de Objetos de JavaScript) es un formato ligero de intercambio de datos. Leerlo y escribirlo es simple para humanos, mientras que para las máquinas es simple interpretarlo y generarlo.

Json Input

# los archivos pueden estar en un link de internet
df4 = pd.read_json("http://pythonhow.com/supermarkets.json")
df4

AddressCityCountryEmployeesIDNameState
03666 21st StSan FranciscoUSA81MadeiraCA 94114
1735 Dolores StSan FranciscoUSA152Bready ShopCA 94119
2332 Hill StSan FranciscoUSA253Super RiverCalifornia 94114
33995 23rd StSan FranciscoUSA104Ben's ShopCA 94114
41056 Sanchez StSan FranciscoUSA125SanchezCalifornia
5551 Alvarado StSan FranciscoUSA206RichvalleyCA 94114

Json output

#Para grabar
df4.to_json("Salida.json")

HTML

Pandas puede leer tablas de html

La función pandas read_html leerá las tablas de una página web y devolverá una lista de objetos DataFrame:

data = pd.read_html('http://www.fdic.gov/bank/individual/failed/banklist.html')
data[0]

Bank NameCitySTCERTAcquiring InstitutionClosing DateUpdated Date
0The Enloe State BankCooperTX10716Legend Bank, N. A.May 31, 2019June 5, 2019
1Washington Federal Bank for SavingsChicagoIL30570Royal Savings BankDecember 15, 2017February 1, 2019
2The Farmers and Merchants State Bank of ArgoniaArgoniaKS17719Conway BankOctober 13, 2017February 21, 2018
3Fayette County BankSaint ElmoIL1802United Fidelity Bank, fsbMay 26, 2017January 29, 2019
4Guaranty Bank, (d/b/a BestBank in Georgia & Mi...MilwaukeeWI30003First-Citizens Bank & Trust CompanyMay 5, 2017March 22, 2018
5First NBC BankNew OrleansLA58302Whitney BankApril 28, 2017January 29, 2019
6Proficio BankCottonwood HeightsUT35495Cache Valley BankMarch 3, 2017January 29, 2019
7Seaway Bank and Trust CompanyChicagoIL19328State Bank of TexasJanuary 27, 2017January 29, 2019
8Harvest Community BankPennsvilleNJ34951First-Citizens Bank & Trust CompanyJanuary 13, 2017May 18, 2017
9Allied BankMulberryAR91Today's BankSeptember 23, 2016May 13, 2019
10The Woodbury Banking CompanyWoodburyGA11297United BankAugust 19, 2016December 13, 2018
11First CornerStone BankKing of PrussiaPA35312First-Citizens Bank & Trust CompanyMay 6, 2016November 13, 2018
12Trust Company BankMemphisTN9956The Bank of Fayette CountyApril 29, 2016September 14, 2018
13North Milwaukee State BankMilwaukeeWI20364First-Citizens Bank & Trust CompanyMarch 11, 2016January 29, 2019
14Hometown National BankLongviewWA35156Twin City BankOctober 2, 2015February 19, 2018
15The Bank of GeorgiaPeachtree CityGA35259Fidelity BankOctober 2, 2015July 9, 2018
16Premier BankDenverCO34112United Fidelity Bank, fsbJuly 10, 2015February 20, 2018
17Edgebrook BankChicagoIL57772Republic Bank of ChicagoMay 8, 2015January 29, 2019
18Doral Bank En EspañolSan JuanPR32102Banco Popular de Puerto RicoFebruary 27, 2015January 29, 2019
19Capitol City Bank & Trust CompanyAtlantaGA33938First-Citizens Bank & Trust CompanyFebruary 13, 2015January 29, 2019
20Highland Community BankChicagoIL20290United Fidelity Bank, fsbJanuary 23, 2015November 15, 2017
21First National Bank of CrestviewCrestviewFL17557First NBC BankJanuary 16, 2015November 15, 2017
22Northern Star BankMankatoMN34983BankVistaDecember 19, 2014January 3, 2018
23Frontier Bank, FSB D/B/A El Paseo BankPalm DesertCA34738Bank of Southern California, N.A.November 7, 2014November 10, 2016
24The National Republic Bank of ChicagoChicagoIL916State Bank of TexasOctober 24, 2014January 6, 2016
25NBRS FinancialRising SunMD4862Howard BankOctober 17, 2014January 29, 2019
26GreenChoice Bank, fsbChicagoIL28462Providence Bank, LLCJuly 25, 2014December 12, 2016
27Eastside Commercial BankConyersGA58125Community & Southern BankJuly 18, 2014October 6, 2017
28The Freedom State BankFreedomOK12483Alva State Bank & Trust CompanyJune 27, 2014February 21, 2018
29Valley BankFort LauderdaleFL21793Landmark Bank, National AssociationJune 20, 2014January 29, 2019
........................
526ANB Financial, NABentonvilleAR33901Pulaski Bank and Trust CompanyMay 9, 2008February 1, 2019
527Hume BankHumeMO1971Security BankMarch 7, 2008January 31, 2019
528Douglass National BankKansas CityMO24660Liberty Bank and Trust CompanyJanuary 25, 2008October 26, 2012
529Miami Valley BankLakeviewOH16848The Citizens Banking CompanyOctober 4, 2007September 12, 2016
530NetBankAlpharettaGA32575ING DIRECTSeptember 28, 2007January 31, 2019
531Metropolitan Savings BankPittsburghPA35353Allegheny Valley Bank of PittsburghFebruary 2, 2007October 27, 2010
532Bank of EphraimEphraimUT1249Far West BankJune 25, 2004April 9, 2008
533Reliance BankWhite PlainsNY26778Union State BankMarch 19, 2004April 9, 2008
534Guaranty National Bank of TallahasseeTallahasseeFL26838Hancock Bank of FloridaMarch 12, 2004April 17, 2018
535Dollar Savings BankNewarkNJ31330No AcquirerFebruary 14, 2004April 9, 2008
536Pulaski Savings BankPhiladelphiaPA27203Earthstar BankNovember 14, 2003October 6, 2017
537First National Bank of BlanchardvilleBlanchardvilleWI11639The Park BankMay 9, 2003June 5, 2012
538Southern Pacific BankTorranceCA27094Beal BankFebruary 7, 2003October 20, 2008
539Farmers Bank of CheneyvilleCheneyvilleLA16445Sabine State Bank & TrustDecember 17, 2002October 20, 2004
540Bank of AlamoAlamoTN9961No AcquirerNovember 8, 2002March 18, 2005
541AmTrade International Bank En EspañolAtlantaGA33784No AcquirerSeptember 30, 2002September 11, 2006
542Universal Federal Savings BankChicagoIL29355Chicago Community BankJune 27, 2002October 6, 2017
543Connecticut Bank of CommerceStamfordCT19183Hudson United BankJune 26, 2002February 14, 2012
544New Century BankShelby TownshipMI34979No AcquirerMarch 28, 2002March 18, 2005
545Net 1st National BankBoca RatonFL26652Bank Leumi USAMarch 1, 2002April 9, 2008
546NextBank, NAPhoenixAZ22314No AcquirerFebruary 7, 2002February 5, 2015
547Oakwood Deposit Bank Co.OakwoodOH8966The State Bank & Trust CompanyFebruary 1, 2002October 25, 2012
548Bank of Sierra BlancaSierra BlancaTX22002The Security State Bank of PecosJanuary 18, 2002November 6, 2003
549Hamilton Bank, NA En EspañolMiamiFL24382Israel Discount Bank of New YorkJanuary 11, 2002September 21, 2015
550Sinclair National BankGravetteAR34248Delta Trust & BankSeptember 7, 2001October 6, 2017
551Superior Bank, FSBHinsdaleIL32646Superior Federal, FSBJuly 27, 2001August 19, 2014
552Malta National BankMaltaOH6629North Valley BankMay 3, 2001November 18, 2002
553First Alliance Bank & Trust Co.ManchesterNH34264Southern New Hampshire Bank & TrustFebruary 2, 2001February 18, 2003
554National State Bank of MetropolisMetropolisIL3815Banterra Bank of MarionDecember 14, 2000March 17, 2005
555Bank of HonoluluHonoluluHI21029Bank of the OrientOctober 13, 2000March 17, 2005

556 rows × 7 columns


SQL

El módulo pandas.io.sql proporciona una colección de contenedores de consultas para facilitar la recuperación de datos y reducir la dependencia de la API específica de DB. La abstracción de la base de datos es proporcionada por SQLAlchemy si está instalado. Además, necesitará una biblioteca de controladores para su base de datos. Ejemplos de tales controladores son psycopg2 para PostgreSQL o pymysql para MySQL. Para SQLite esto está incluido en la biblioteca estándar de Python por defecto. Puede encontrar una descripción general de los controladores admitidos para cada lenguaje SQL en los documentos de SQLAlchemy.

Vea también algunos ejemplos de libros para algunas estrategias avanzadas.

las funciones claves son:

  • read_sql_table(table_name, con[, schema, …])
    • Read SQL database table into a DataFrame.
  • read_sql_query(sql, con[, index_col, …])
    • Read SQL query into a DataFrame.
  • read_sql(sql, con[, index_col, …])
    • Read SQL query or database table into a DataFrame.
  • DataFrame.to_sql(name, con[, flavor, …])
    • Write records stored in a DataFrame to a SQL database.
# librerias para crear un proceso de sql sencillo
from sqlalchemy import create_engine
# crear un proceso en memoria
engine = create_engine('sqlite:///:memory:')
df4.to_sql('data', engine) # grabar el dataframe en formato sql
sql_df = pd.read_sql('data',con=engine) # definir la conexion
sql_df

indexAddressCityCountryEmployeesIDNameState
003666 21st StSan FranciscoUSA81MadeiraCA 94114
11735 Dolores StSan FranciscoUSA152Bready ShopCA 94119
22332 Hill StSan FranciscoUSA253Super RiverCalifornia 94114
333995 23rd StSan FranciscoUSA104Ben's ShopCA 94114
441056 Sanchez StSan FranciscoUSA125SanchezCalifornia
55551 Alvarado StSan FranciscoUSA206RichvalleyCA 94114

Referencias

Phd. Jose R. Zapata