on
, left_on
y right_on
en merge
para especificar qué columnas se deben usar para casar filas al combinar los dos DataFrames
¶Vimos que, por defecto, merge
usa las columnas comunes en ambos DataFrame
s para casar las filas
# Preliminares
import pandas as pd
import numpy as np
Consideramos los dos DataFrame
s:
clientes= pd.DataFrame(
{'dni': ['12345678', '23456789', '34567890', '01234567'],
'nombre': ['José', 'Pedro', 'María', 'Blanca'],
'apellido1': ['Pérez', 'Martínez', 'Sánchez', 'Ruiz'],
'apellido2': ['Martínez', 'Moreno', 'Meseguer', 'Torres']
}
)
clientes
dni | nombre | apellido1 | apellido2 | |
---|---|---|---|---|
0 | 12345678 | José | Pérez | Martínez |
1 | 23456789 | Pedro | Martínez | Moreno |
2 | 34567890 | María | Sánchez | Meseguer |
3 | 01234567 | Blanca | Ruiz | Torres |
pedidos= pd.DataFrame(
{'id': [10, 12, 21, 22, 24, 25, 28],
'dni': np.repeat(['23456789','12345678', '34567890', '87654321'], repeats=[2, 3, 1, 1]),
'id_producto': ['AAA123', 'SOX433', 'QWE000', 'SOX433', 'PII342', 'ZXY099','PII342']})
pedidos
id | dni | id_producto | |
---|---|---|---|
0 | 10 | 23456789 | AAA123 |
1 | 12 | 23456789 | SOX433 |
2 | 21 | 12345678 | QWE000 |
3 | 22 | 12345678 | SOX433 |
4 | 24 | 12345678 | PII342 |
5 | 25 | 34567890 | ZXY099 |
6 | 28 | 87654321 | PII342 |
Consideramos ahora un DataFrame
adicional
productos = pd.DataFrame({
'id': ['AAA123', 'SOX433', 'QWE000', 'PII342', 'ZXY099'],
'nombre': ['Pila', 'Bombilla', 'Interruptor', 'Enchufe', 'Toma']})
productos
id | nombre | |
---|---|---|
0 | AAA123 | Pila |
1 | SOX433 | Bombilla |
2 | QWE000 | Interruptor |
3 | PII342 | Enchufe |
4 | ZXY099 | Toma |
Queremos añadir la información de cada producto al
DataFrame
de los pedidos de cada cliente.
merge
usa las columnas en común¶Creemos el DataFrame
de clientes_pedidos
clientes_pedidos = clientes.merge(pedidos, how='left')
clientes_pedidos
dni | nombre | apellido1 | apellido2 | id | id_producto | |
---|---|---|---|---|---|---|
0 | 12345678 | José | Pérez | Martínez | 21.0 | QWE000 |
1 | 12345678 | José | Pérez | Martínez | 22.0 | SOX433 |
2 | 12345678 | José | Pérez | Martínez | 24.0 | PII342 |
3 | 23456789 | Pedro | Martínez | Moreno | 10.0 | AAA123 |
4 | 23456789 | Pedro | Martínez | Moreno | 12.0 | SOX433 |
5 | 34567890 | María | Sánchez | Meseguer | 25.0 | ZXY099 |
6 | 01234567 | Blanca | Ruiz | Torres | NaN | NaN |
clientes_pedidos
con la información de productos¶En este caso, intentará casar las columnas
nombre
yid
clientes_pedidos.merge(productos)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-6-10fa1c934ab0> in <module> ----> 1 clientes_pedidos.merge(productos) ~\Anaconda3\lib\site-packages\pandas\core\frame.py in merge(self, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, copy, indicator, validate) 8203 copy=copy, 8204 indicator=indicator, -> 8205 validate=validate, 8206 ) 8207 ~\Anaconda3\lib\site-packages\pandas\core\reshape\merge.py in merge(left, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, copy, indicator, validate) 85 copy=copy, 86 indicator=indicator, ---> 87 validate=validate, 88 ) 89 return op.get_result() ~\Anaconda3\lib\site-packages\pandas\core\reshape\merge.py in __init__(self, left, right, how, on, left_on, right_on, axis, left_index, right_index, sort, suffixes, copy, indicator, validate) 670 # validate the merge keys dtypes. We may need to coerce 671 # to avoid incompatible dtypes --> 672 self._maybe_coerce_merge_keys() 673 674 # If argument passed to validate, ~\Anaconda3\lib\site-packages\pandas\core\reshape\merge.py in _maybe_coerce_merge_keys(self) 1191 inferred_right in string_types and inferred_left not in string_types 1192 ): -> 1193 raise ValueError(msg) 1194 1195 # datetimelikes must match exactly ValueError: You are trying to merge on float64 and object columns. If you wish to proceed you should use pd.concat
El error que devuelve es porque la columna id
en los dos DataFrame
s son de diferentes tipos. No se pueden unir usando dos columnas que no sean del mismo tipo.
# Comprobamos tipos
clientes_pedidos.dtypes
dni object nombre object apellido1 object apellido2 object id float64 id_producto object dtype: object
# Comprobamos tipos
productos.dtypes
id object nombre object dtype: object
id
es de tipofloat64
enclientes_pedidos
y de tipostr
(string) enproductos
.
Cambiamos el tipo de id
en clientes_pedidos
:
clientes_pedidos['id'] = clientes_pedidos['id'].astype(str)
Volvemos a intentar el merge
clientes_pedidos.merge(productos)
dni | nombre | apellido1 | apellido2 | id | id_producto |
---|
Como era esperado, obtenemos ahora un
DataFrame
vacío porque las columnas comunesid
ynombre
no contienen información sobre los mismos elementos y no tienen valores en común.
Para empezar, vamos a cambiar los nombres de las columnas conflictivas de productos
productos.rename(columns={'nombre': 'nombre_producto'}, inplace=True)
productos
id | nombre_producto | |
---|---|---|
0 | AAA123 | Pila |
1 | SOX433 | Bombilla |
2 | QWE000 | Interruptor |
3 | PII342 | Enchufe |
4 | ZXY099 | Toma |
Ahora vamos a usar los argumentos
left_on
yright_on
para especificar sobre qué columna delDataFrame
de la izquierda y qué columna delDataFrame
de la derecha nos vamos a basar para casar filas
clientes_pedidos.merge(productos, left_on='id_producto', right_on='id')
dni | nombre | apellido1 | apellido2 | id_x | id_producto | id_y | nombre_producto | |
---|---|---|---|---|---|---|---|---|
0 | 12345678 | José | Pérez | Martínez | 21.0 | QWE000 | QWE000 | Interruptor |
1 | 12345678 | José | Pérez | Martínez | 22.0 | SOX433 | SOX433 | Bombilla |
2 | 23456789 | Pedro | Martínez | Moreno | 12.0 | SOX433 | SOX433 | Bombilla |
3 | 12345678 | José | Pérez | Martínez | 24.0 | PII342 | PII342 | Enchufe |
4 | 23456789 | Pedro | Martínez | Moreno | 10.0 | AAA123 | AAA123 | Pila |
5 | 34567890 | María | Sánchez | Meseguer | 25.0 | ZXY099 | ZXY099 | Toma |
merge
ha añadido sufijos a los nombres de las columnas comunes para diferenciarlas, podríamos haber especificado nuestros propios sufijos con el parámetro suffixes
clientes_pedidos.merge(productos, left_on='id_producto', right_on='id', suffixes=['_pedido','_producto'])
dni | nombre | apellido1 | apellido2 | id_pedido | id_producto | id_producto | nombre_producto | |
---|---|---|---|---|---|---|---|---|
0 | 12345678 | José | Pérez | Martínez | 21.0 | QWE000 | QWE000 | Interruptor |
1 | 12345678 | José | Pérez | Martínez | 22.0 | SOX433 | SOX433 | Bombilla |
2 | 23456789 | Pedro | Martínez | Moreno | 12.0 | SOX433 | SOX433 | Bombilla |
3 | 12345678 | José | Pérez | Martínez | 24.0 | PII342 | PII342 | Enchufe |
4 | 23456789 | Pedro | Martínez | Moreno | 10.0 | AAA123 | AAA123 | Pila |
5 | 34567890 | María | Sánchez | Meseguer | 25.0 | ZXY099 | ZXY099 | Toma |