Archivo de la etiqueta: Pandas

Tipos de uniones (join) de tablas con Python Pandas

Recopilación de las uniones más habituales con Python Pandas en una sola entrada. No se realiza equivalencias con sql join, la intención es tener de forma resumida los códigos para realizar left join inner join y concatenación de data frames de Pandas. Hay amplia documentación esto es una síntesis.

Los data frames empleados para ilustrar el ejemplo son:

import pandas as pd
import numpy as np
ejemplo = { "variable1": [10, 20, 30, 40],
            "variable2": [100, 200, 300, 400]
}
anio=["2011", "2012", "2013", "2014"]
df1 = pd.DataFrame(ejemplo,index=anio)
df1
ejemplo = { "variable1": [50, 60, 70, 80],
            "variable3": [5000, 6000, 7000, 8000]
}
anio=["2013", "2014", "2015", "2016"]
df2 = pd.DataFrame(ejemplo,index=anio)
df2

Uniones de data frames con índices

La estructura de una join con Pandas es:

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
     left_index=False, right_index=False, sort=True,
     suffixes=('_x', '_y'), copy=True, indicator=False,
     validate=None)

Left Join

left_join = pd.merge(df1, df2, how='left', on=None, left_on=None, right_on=None,
         left_index=True, right_index=True, sort=True)
left_join

Outer Join

outer_join = pd.merge(df1, df2, how='outer', on=None, left_on=None, right_on=None,
         left_index=True, right_index=True, sort=True)
outer_join

Right Join

right_join = pd.merge(df1, df2, how='right', on=None, left_on=None, right_on=None,
         left_index=True, right_index=True, sort=True)
right_join

Inner Join

inner_join = pd.merge(df1, df2, how='inner', on=None, left_on=None, right_on=None,
         left_index=True, right_index=True, sort=True)
inner_join

Concatenar

Concatenación simple

concatenar = pd.concat([df1,df2])
concatenar

Concatenación inner

concatenar_inner = pd.concat([df1,df2],join="inner")
concatenar_inner

Concatenación outer

concatenar_outer = pd.concat([df1,df2],join="outer")
concatenar_outer

Uniones sin índices

Data frames de ejemplo análogos a los anteriores.

import pandas as pd
import numpy as np
ejemplo = { "variable1": [10, 20, 30, 40],
            "variable2": [100, 200, 300, 400],
            "anio":      ["2011", "2012", "2013", "2014"]
}

df1 = pd.DataFrame(ejemplo)

ejemplo = { "variable1": [50, 60, 70, 80],
            "variable3": [5000, 6000, 7000, 8000],
            "anio":      ["2013", "2014", "2015", "2016"]
}

df2 = pd.DataFrame(ejemplo)

Si no tenemos índices es importante especificar en el parámetro on= la variable con la que hacemos la unión de las tablas. En este caso ponemos todas las uniones:

Left, outer, right con campo de unión común

left_join = pd.merge(df1, df2, how='left', on='anio')
outer_join = pd.merge(df1, df2, how='outer', left_on=df1['anio'], right_on=df2['anio'])
right_join = pd.merge(df1, df2, how='right', on='anio')

Inner join con campo de unión de distinto nombre

#Renombramos la variable anio
df2 = df2.rename(columns={"anio": "fecha"})
inner_join = pd.merge(df1, df2, how='inner', left_on='anio', right_on='fecha')

Uniones más habituales en una sola entrada y en pocas líneas de código.

Leer archivos Excel con Python

Entrada sobre la importación de Excel con Python, un aporte que sirve para mi documentación y que es posible que sea de ayuda para muchos que se estén iniciando en el uso de Python y Pandas, aunque en este caso para la lectura del Excel usaremos tanto Pandas como la librería xlrd.

Lectura de Excel con Pandas

Lo más sencillo para importarnos en Python un Excel y crearnos un data frame de Pandas es:

import pandas as pd
archivo = 'C:/Users/Documents/ejemplo.xlsx'

df = pd.read_excel(archivo, sheetname='Hoja1')

df.describe()

La función read_excel será suficiente en el 80% de las ocasiones que realicemos esta tarea. Como es habitual en la ayuda tenéis perfectamente descritas sus posibilidades.

Lectura de Excel con xlrd

Es posible que necesitemos realizar tareas más complejas a la hora de leer archivos Excel y podemos usar xlrd. Vemos algunas de las posibilidades:

import xlrd 
 
archivo = 'C:/Users/rvaquerizo/Documents/ejemplo.xlsx'
  
wb = xlrd.open_workbook(archivo) 

hoja = wb.sheet_by_index(0) 
print(hoja.nrows) 
print(hoja.ncols) 
print(hoja.cell_value(0, 0))

open_workbook nos abre el Excel para trabajar con él. Seleccionamos hojas por índice (empezando por el 0) y con la hoja seleccionada podemos ver el número de filas (nrows) o columnas (ncols). Seleccionar una celda lo hacemos con cell_value mediante índices (empezando por el 0). Otras posibilidades:

archivo = 'C:/Users/rvaquerizo/Documents/ejemplo.xlsx'
  
wb = xlrd.open_workbook(archivo) 

hoja = wb.sheet_by_name('Hoja1') 
for i in range(0,hoja.nrows):
    print(hoja.cell_value(i,1))

Si por ejemplo deseamos saber las cabeceras, los nombres de las columnas:

archivo = 'C:/Users/rvaquerizo/Documents/ejemplo.xlsx'
  
wb = xlrd.open_workbook(archivo) 

hoja = wb.sheet_by_index(0) 
nombres = hoja.row(0)  
print(nombres)

Y mediante xlrd podemos crear data frames de pandas con lo que es posible realizar lecturas de rangos:

archivo = 'C:/Users/rvaquerizo/Documents/ejemplo.xlsx'
  
wb = xlrd.open_workbook(archivo) 

hoja = wb.sheet_by_index(0) 

# Creamos listas
filas = []
for fila in range(1,hoja.nrows):
    columnas = []
    for columna in range(0,2):
        columnas.append(hoja.cell_value(fila,columna))
    filas.append(columnas)

import pandas as pd
df = pd.DataFrame(filas)
df.head()

Hay alguna librería que lo hace de forma más elegante pero la importación de rangos de Excel con xlrd, una vez te familiarizas, me parece bastante sencilla. Espero que sea de utilidad

Lectura de archivos csv con Python y Pandas

A continuación os planteo un acercamiento básico a la lectura de archivos csv con Python y algunos trucos para facilitar la vida cuando realizamos importaciones basados en la experiencia como son leer los primeros registros del csv o realizar una lectura de observaciones aleatoria por si el archivo es muy voluminoso. Para realizar las importaciones vamos a emplear Pandas y la función read_csv con sus infititas opciones:

 pd.read_csv(filepath_or_buffer, sep=', ', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression='infer', thousands=None, decimal=b'.', lineterminator=None, quotechar='"', quoting=0, escapechar=None, comment=None, encoding=None, dialect=None, tupleize_cols=None, error_bad_lines=True, warn_bad_lines=True, skipfooter=0, doublequote=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None)

Para trabajar la entrada vamos a necesitar dos archivos de texto:

Como costumbre poner la ubicación del archivo y después la lectura:

path = 'C:/temp/'

import pandas as pd
df = pd.read_csv (path + 'index.csv')
df.head()

En este caso la vida es maravillosa y ha salido todo a la primera pero sabemos que eso no pasa siempre, ejecutáis:

df = pd.read_csv (path + 'bank-additional-full.csv')
df.head()

El separador es distinto:

df = pd.read_csv (path + 'bank-additional-full.csv', sep = ';')
df.head()

La vida sigue sin ser muy complicada porque el archivo de ejemplo tiene pocos registros, pero imaginad que leéis unas docenas de GB por ello previamente es mejor ejecutar:

df = pd.read_csv (path + 'bank-additional-full.csv', nrows= 200)
df.shape

con nrows = 200 leemos las primeras 200 líneas y podemos comprobar si lo estamos leyendo correctamente y podemos ahorrarnos disgustos, tiempo y trabajo. E incluso estaría bien no leer las docenas de GB porque no tenemos suficiente memoria o porque no necesitamos leer entero el archivo podemos leer por trozos:

meses = ['may', 'jul']
df = pd.DataFrame()
for trozo in pd.read_csv(path + 'bank-additional-full.csv', sep=';',
                             chunksize=1000):
    df = pd.concat([df,trozo[trozo['month'].isin(meses)]])

df.month.value_counts()

Con chunksize estamos leyendo el archivo csv en trozos (chunks) de 1000 en 1000 y nos quedamos sólo con aquellos que cumplan un determinado requisito, en este caso que el campo month sea may o jul. E incluso podéis leer el csv extrayendo una muestra aleatoria mientras leéis el fichero por partes y no sobre pasar la memoria:

df2 = pd.DataFrame()
for trozo in pd.read_csv(path + 'bank-additional-full.csv', sep=';',
                             chunksize=1000):
    df2 = pd.concat([df2,trozo.sample(frac=0.25)])
df2.shape

Este último truco puede servir para leer csv extremadamente grandes y realizar los primeros análisis aproximativos a nuestro problema porque como dice un buen amigo “si en 200.000 registros no encuentras una señal no hace falta que cargues millones”.

Data Management básico con Pandas

Entrada dedicada al manejo de datos más básico con Python y Pandas, es análoga a otra ya realizada con dplyr para R. Sirve para tener en un vistazo las tareas más habituales que realizamos en el día a día con Pandas. Para aquel que se esté introduciendo al uso de Python puede ser de utilidad tener todo junto y más claro, a mi personalmente me sirve para no olvidar cosas que ya no uso. En una sola entrada recogemos las dudas más básicas cuando nos estamos iniciando con Python. Las tareas más comunes son:

  • Seleccionar columnas
  • Eliminar columnas
  • Seleccionar registros
  • Crear nuevas variables
  • Sumarizar datos
  • Ordenar datos

Para variar vamos a emplear el conjunto de datos iris y que nos descargamos directamente de una url para ello las primeras sentencias que hemos de ejecutar son las siguientes:

import pandas as pd
import io
import requests
url='https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv'
s=requests.get(url).content
df=pd.read_csv(io.StringIO(s.decode('utf-8')))

Este código es un buen ejemplo de como obtener un csv directamente de una url porque en ocasiones pueden surgir problemas.

Seleccionar columnas con Pandas Python:
Directamente

df2 = df[['sepal_length','sepal_width']]
df2.head()

Mediante una lista, parece más claro.

seleccionadas = ['sepal_length','sepal_width']
df2 = df[seleccionadas]
df2.head()

Eliminar columnas:

df3 = df.drop(columns=['sepal_length','sepal_width'])
df3.head()

Seleccionar registros con Pandas Python:

Con condiciones simples, los operadores se pueden consultar pero no son “extraños”. También se presenta la función value_counts() que es una sumarización muy habitual.

df['species'].value_counts()
df4 = df[df['species']=="setosa"]
df4['species'].value_counts()

Algo que tiene especial relevancia (desde mi punto de vista) son los paréntesis en condiciones complejas o múltiples cuando usamos Pandas.

df5 = df.loc[(df.sepal_length<5) & (df.species=="setosa")]
df6 = df[(df['sepal_length']<5) & (df['species'] != "setosa")]

Particularmente la función isin para hacer condiciones del tipo in en listas la encuentro de mucha utilidad.

lista = ['setosa', 'virginica']
df7 = df[df['species'].isin(lista)]
df7['species'].value_counts()

Crear nuevas variables con Pandas Python:

df['sepal_length_tipi'] = df['sepal_length']/df['sepal_length'].mean()
df['sepal_length_tipi'].describe()

En este sentido destacaría el uso de la función de numpy where, el famoso np.where que trabaja igual que el ifelse de R.

import numpy as np

df['sepal_length_altas'] = np.where(df['sepal_length'] > np.mean(df['sepal_length']),
                                    "Por encima de la media", "Por debajo de la media")
df['sepal_length_altas'].value_counts()

Sumarizar datos con Pandas Python:

df[['sepal_length','species']].groupby('species').mean()
df[['sepal_length','species']].groupby('species').count()

Sumarizar por múltiples columnas tienes que listar variables.

df.groupby(['species','sepal_length_altas']).min()

Ordenar data frames con Pandas Python:

df8 = df.sort_values('sepal_length',ascending=[True])

Si queremos ordenar por múltiples campos del data frame con distintos órdenes:

df9 = df.sort_values(['sepal_length','sepal_width'],ascending=[True,False])

Pero en pocas líneas quedan recogidas las principales tareas con registros y columnas que se pueden hacer en un data frame con Pandas. La siguiente entrada irá encaminada a la unión de data frames con Python y Pandas.

Truco Python. Reemplazar una cadena de caracteres en los nombres de las columnas de un data frame

Más largo el título de la entrada que la entrada en si misma. Tenemos un conjunto de datos que os podéis descargar de este link que ya es conocido. Os descargáis los datos y creamos un data frame que tiene 10.000 registros y 251 columnas, casi todas se llaman attx y queremos cambiar el nombre a columna_x. Mi sugerencia para hacerlo vía pandas es:

import pandas as pd
df = pd.read_csv('C:\temp\wordpress\au2_10000.csv')
df.head()

df.columns = df.columns.str.replace('att','columna_')
df.head()

Espero que sea de utilidad. Saludos.