• Saltar a la navegación principal
  • Saltar al contenido principal
Logo Codificando Bits

Codificando Bits

  • Academia
    • Rutas
    • Cursos
    • Proyectos
    • Tutoriales
  • Acceder
  • Suscribirse

Análisis Exploratorio de Datos con Python y Pandas: un ejemplo práctico

El Análisis Exploratorio de Datos (EDA) es uno de los pasos fundamentales en cualquier proyecto de Ciencia de Datos o Machine Learning, pues nos permito no solo comenzar a entender los datos que estamos procesando, sino también construir un «mapa mental» de la información que contienen estos datos, lo cual resulta fundamental para las posteriores fases del proyecto.

Así que en este tutorial realizaremos un ejercicio práctico de EDA utilizando un set de datos de marketing bancario. Con esto aprenderemos a utilizar herramientas estadísticas y de visualización para extraer conocimiento oculto en los datos y para además responder preguntas de negocio.

Al final de este tutorial, se encuentran los enlaces para descargar el set de datos y el código fuente.

El problema de negocio

Para este ejercicio, nos situamos en el contexto de una entidad bancaria que ha contratado a una empresa de marketing.

El objetivo de la empresa es contactar telefónicamente a posibles clientes para determinar si están interesados en adquirir un certificado de depósito a término (CDT).

Y el punto de partida de este análisis exploratorio, como en todos los proyectos de Ciencia de Datos, es una pregunta de negocio. En este caso intentaremos responder a esta pregunta:¿qué perfil tienen los clientes con mayor potencial de conversión?

Preparación del entorno y lectura de datos

Comenzaremos importando las librerías esenciales para el análisis: Pandas para la manipulación de estructuras de datos y Matplotlib junto con Seaborn para la generación de visualizaciones estadísticas:

# Importar librerías
import pandas as pd
import matplotlib.pyplot as plt
import sns as sns

# Lectura del dataset limpio
ruta = "dataset_banco_clean.csv"
data = pd.read_csv(ruta)

print(data.shape)
data.head()

Las anteriores líneas de código nos permiten importar las librerías para realizar el análisis exploratorio (líneas 2 a 4), cargar el set de datos que se encuentra en formato CSV (líneas 7 y 8) y mostrar el tamaño del dataset y las primeras filas (líneas 10 y 11).

Al ejecutar el código anterior podremos ver que el set de datos cuenta con 45,189 filas y 17 columnas, que incluyen las siguientes variables (también llamadas «características», que son simplemente las columnas en la tabla de datos.

El paso inicial es entender qué tipo de información contiene cada columna. Supondremos que esta información ya fue proporcionada por el equipo de marketing y a continuación se resume el significado de cada columna así como el tipo de variable que tendremos (numérica o categórica):

1. «age»: edad (numérica)

2. «job»: tipo de trabajo (categórica)

3. «marital»: estado civil (categórica)

4. «education»: nivel educativo (categórica)

5. «default»: si dejó de pagar sus obligaciones (categórica)

6. «balance»: saldo promedio anual en euros (numérica)

7. «housing»: ¿tiene o no crédito hipotecario? (categórica)

8. «loan»: ¿tiene créditos de consumo? (categórica)

9. «contact»: medio a través del cual fue contactado (categórica)

10. «day»: último día del mes en el que la persona fue contactada (numérica)

11. «month»: último mes en el que la persona fue contactada (categórica)

12. «duration»: duración (en segundos) del último contacto (numérica)

13. «campaign»: número total de veces que fue contactada la persona durante la campaña (numérica)

14. «pdays»: número de días transcurridos después de haber sido contactado antes de la campaña actual (numérica. -1 indica que no fue contactado previamente)

15. «previous»: número de veces que la persona ha sido contactada antes de esta campaña (numérica)

16. «poutcome»: resultado de la campaña de marketing anterior (categórica)

17. «y»: categoría ¿el cliente se suscribió a un depósito a término? (categórica)

Esta última columna es clave pues nos indica si el cliente adquirió el CDT o no y, por tanto, está directamente relacionada con la pregunta que nos planteamos inicialmente.

Muy bien, una vez hayamos cargado el set de datos ya podremos dar inicio a su análisis exploratorio.

Fases del Análisis Exploratorio

Dividiremos nuestro análisis en tres fases lógicas (que son las fases que recomiendo usualmente llevar a cabo al realizar el EDA en un proyecto de Ciencia de Datos):

  1. Análisis de cada variable de manera individual, para entender las características generales de las columnas.
  2. Análisis univariado, para establecer las posibles relaciones que existen entre la variable de interés y las demás columnas del dataset.
  3. Análisis bivariado donde, como su nombre la indica, analizamos la relación entre pares de variables.

Y recordemos que todas las fases de este análisis exploratorio están encaminadas a responder a la pregunta que nos planteamos inicialmente en el proyecto (que para este caso es «¿qué perfil tienen los clientes con mayor potencial de conversión?»).


Fase 1: análisis de variables individuales

Primero, identificamos los tipos de datos presentes en el DataFrame para separar variables numéricas de categóricas, para lo cual podemos usar el método «info()» de Pandas:

data.info()

Al ejecutar la línea de código anterior veremos en pantalla una tabla que resume las principales características del set de datos:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 45189 entries, 0 to 45188
Data columns (total 17 columns):
 #   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  
 0   age        45189 non-null  int64  
 1   job        45189 non-null  object 
 2   marital    45189 non-null  object 
 3   education  45189 non-null  object 
 4   default    45189 non-null  object 
 5   balance    45189 non-null  float64
 6   housing    45189 non-null  object 
 7   loan       45189 non-null  object 
 8   contact    45189 non-null  object 
 9   day        45189 non-null  int64  
 10  month      45189 non-null  object 
 11  duration   45189 non-null  float64
 12  campaign   45189 non-null  int64  
 13  pdays      45189 non-null  float64
 14  previous   45189 non-null  int64  
 15  poutcome   45189 non-null  object 
 16  y          45189 non-null  object 
dtypes: float64(3), int64(4), object(10)
memory usage: 5.9+ MB

Por ejemplo:

  • En la línea 2 vemos que el set de datos tiene un total de 45189 entradas (o filas), mientras que el número de columnas es 17 (línea 3)
  • Y además, en las líneas 4 a 22 vemos un resumen de las características de cada columna. En este resumen se indica el índice de la columna («#»), el nombre («Column»), la cantidad de datos no nulos («Non-Null Count») y el tipo de dato que («Dtype»)

Estos dos últimos elementos (cantidad de datos no nulos y tipo de dato) resultan claves en la exploración: la cantidad de datos no nulos nos permite ver si la columna contiene datos faltantes (celdas vacías), mientras que el tipo de dato nos da una indicación del tipo de variable que podríamos tener.

Por ejemplo, vemos que en todas las columnas el conteo de datos no nulos concide perfectamente con el número total de registros (45189) lo que nos permite concluir que nuestro dataset no contiene datos faltantes.

Por otra parte, las columnas con tipos de dato «int64» o «float64» son columnas que contienen variables numéricas (como por ejemplo las columnas «age», «balance» y «month», entre otras), mientras que las columnas con tipos de dato «object» usualmente contienen variables categóricas (como por ejemplo es el caso de «job», «housing» y «y»).

Continuando con este análisis de variables individuales, nos enfocaremos inicialmente en las variables categóricas.

Variables categóricas

Una herramienta muy útil al momento de analizar este tipo de variables son los gráficos de barras, que nos permiten visualizar la distribución de los niveles en cada categoría.

Comencemos generando un listado de las variables (columnas) categóricas dentro de nuestro set de datos (es decir las variables con tipos de dato «object»):

col_cat = ['job', 'marital', 'education', 'default', 'housing',
           'loan', 'contact', 'month', 'poutcome', 'y']

A continuación usaremos Matplotlib para generar una grilla que tendrá una sola columna y un número de filas igual al número de variables categóricas:

fig, ax = plt.subplots(nrows=len(col_cat), ncols=1, figsize=(10,45))
fig.subplots_adjust(hspace=0.5)

Y finalmente, usamos la función «countplot» de la librería Seaborn para generar los gráficos correspondientes:

# Gráficos de barras de conteo
for i, col in enumerate(col_cat):
  sns.countplot(x=col, data=data, ax=ax[i])
  ax[i].set_title(col)
  ax[i].set_xticklabels(ax[i].get_xticklabels(), rotation=30)

Al ejecutar el código anterior tendremos un conjunto de gráficos como este:

Gráficos de barras correspondientes a las variables categóricas de nuestro set de datos
Gráficos de barras correspondientes a las variables categóricas de nuestro set de datos

Lo clave siempre en el análisis exploratorio de datos es agregar un conjunto de observaciones de los resultados que obtengamos en cada fase. Estas observaciones nos permitirán al final tener una síntesis de los principales hallazgos de este análisis y, desde luego, nos permitirán responder a la pregunta de negocio que nos planteamos inicialmente.

En este caso, analizando los gráficos obtenidos anteriormente, podríamos escribir estas observaciones:

  • ‘job’: 12 niveles o tipos de trabajo (management, technician, entrepreneur, etc.)
  • ‘marital’: 3 niveles (married, single, divorced)
  • ‘education’: 4 niveles (primary, secondary, tertiary, unknown)
  • ‘default’: 2 niveles (Yes, No). En este caso la gran mayoría de contactados tienen valores ‘No’
  • ‘housing’: 2 niveles (Yes, No). En este caso el set está relativamente balanceado (aproximadamente la misma cantidad de datos para cada nivel).
  • ‘loan’: 2 niveles (Yes, No). En este caso la gran mayoría contiene valores ‘No’.
  • ‘poutcome’: 4 niveles (unknown, failure, other, success). La gran mayoría está en el nivel ‘unknown’
  • ‘y’: 2 niveles (No, Yes). La gran mayoría está en el nivel ‘No’. Si mas adelante se implemente algún modelo predictivo con Machine Learning se debe tener en cuenta este desbalance.

Limpieza durante el EDA

El análisis exploratorio no es un proceso lineal, pues en el camino podremos ir encontrando elementos que nos lleven a explorar más en detalle ciertos aspectos del dataset o a realizar una limpieza de los datos.

En este caso particular, el análisis de las variables categóricas nos permite determinar que variables como el medio de contacto, el mes o la duración de la llamada no definen el perfil intrínseco del cliente para futuras predicciones generales, es decir no guardan relación con la pregunta que nos planteamos inicialmente.

Así que simplemente podemos eliminar estas variables (o columnas) pues resultan irrelevantes para nuestro análisis. Esto lo podemos hacer con el método «drop» de Pandas:

# Eliminemos columnas que no aportan información sobre el perfil del cliente
data.drop(columns=['contact','month', 'day', 'duration', 'campaign', 'pdays',
                   'previous'], inplace=True)
data.columns

Al ejecutar el código anterior tendremos el dataset actualizado que contendrá únicamente las siguientes columnas: ‘age’, ‘job’, ‘marital’, ‘education’, ‘default’, ‘balance’, ‘housing’, ‘loan’, ‘poutcome’, ‘y’.

Así que en este punto ya tenemos un análisis preliminar de las variables categóricas y hemos eliminado aquellas que resultan irrelevantes. Veamos ahora qué sucede con las variables numéricas.

Variables numéricas

En este caso podemos usar el método «describe()» de Pandas. Este método tomará automáticamente las columnas numéricas del dataset e imprimirá en pantalla algunas métricas descriptivas básicas:

# Estadísticas descriptivas básicas
data.describe()

Al ejecutar el código anterior tendremos un resumen descriptivo para las variables «age» y «balance» similar al siguiente:

	age	balance
count	45189.000000	45189.000000
mean	40.936445	1374.012149
std	10.618502	3924.370039
min	18.000000	-8019.000000
25%	33.000000	72.000000
50%	39.000000	448.000000
75%	48.000000	1428.000000
max	95.000000	527532.000000

Este análisis descriptivo preliminar nos permite tener una idea más detallada del comportamiento de estas variables, como por ejemplo sus valores mínimo, máximo, su promedio, los cuartiles y la mediana.

Sin embargo, siempre sugiero usar herramientas de visualización (como los gráficos de caja o los histogramas) para ver en detalle la distribución de cada variable.

Por ejemplo, dibujemos el histograma de estas variables numéricas:

# Dibujar histogramas para age y balance
col_num = ['age', 'balance']
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(15,5))

for i, col in enumerate(col_num):
    nbins = 10 if col == 'age' else 50
    sns.histplot(x=col, data=data, ax=ax[i], bins=nbins, kde=True)
    ax[i].set_title(col)

En el código anterior:

  • Primero creamos una grilla que contendrá los dos histogramas (línea 3)
  • Y luego iteramos por esta grilla usamos Seaborn y el método «histplot» (línea 7) para dibujar cada histograma

Tras ejecutar el código anterior tendremos un resultado como este:

Histogramas de las variables "edad" y "balance" con lo cual podremos ver la distribución de estas variables numéricas
Histogramas de las variables «edad» y «balance» con lo cual podremos ver la distribución de estas variables numéricas

Gracias a estos gráficos, y a la información que obtuvimos con el método «describe()», podemos observar detalles adicionales de estas dos variables:

  • La mayoría de los clientes tienen entre 30 y 50 años, con un sesgo hacia los más jóvenes dentro de ese rango.
  • El 75% de los clientes tiene un saldo menor a 1,500 euros, existiendo incluyendo saldos negativos.

Fase 2: Análisis univariado

En eta fase iremos un paso más allá con el análisis exploratorio, pues lo que buscamos es establecer la relación entre cada variable del dataset y la tasa de conversión. Para facilitar el cálculo, transformaremos esta variable objetivo (columna «y» en nuestro dataset) a un formato binario numérico, para lo cual podemos usar el método «map» de Pandas:

# Convertir variable objetivo a binario: 'yes' = 1, 'no' = 0
diccionario = {'yes': 1, 'no': 0}
data['y_bin'] = data['y'].map(diccionario)

Análisis de variables numéricas frente a la conversión

Comenzaremos haciendo este análisis univariado determinando si existe alguna relación entre las variables numéricas («age» y «balance») y la tasa de conversión (columna «y» que acabamos de transformar).

Para ello utilizaremos diagramas de caja (método «boxplot» en Seaborn) que nos permiten comparar la distribución de edad y saldo entre quienes compraron y quienes no:

# Relación entre variables numéricas e y_bin
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(15,5))
for i, col in enumerate(['age', 'balance']):
  sns.boxplot(x="y_bin", y=col, data=data, ax=ax[i])
  ax[i].set_title(col)

Al ejecutar el código anterior obtenemos este resultado:

Gráficos de caja de las variables "edad" y "balance" con lo cual podremos ver la distribución de estas variables numéricas así como la presencia de valores extremos
Gráficos de caja de las variables «edad» y «balance» con lo cual podremos ver la distribución de estas variables numéricas así como la presencia de valores extremos

Al analizar los gráficos anteriores vemos que no se observan diferencias claras en las medianas de los boxplots. Esto quiere decir que en principio las tasas de conversión no se ven afectadas por las variables edad y saldo.

Sin embargo, estas variables numéricas se encuentran en un amplio rango de valores. Así que podemos profundizar en este análisis calculando las tasas de conversión para las diferentes edades.

Análisis por edad

Entonces implementaremos la función «graficar_tasas_conversion» que nos permitirá agrupar el set de datos por edades y luego dibujar el comportamiento de dichas tasas. Este es el código de Python correspondiente:

# Función para graficar tasas de conversión

def graficar_tasas_conversion(var_predictora, var_predecir, type='line', order=None):
    x, y = var_predictora, var_predecir

    # Generar agrupaciones (groupby), calcular tasa de conversión (mean),
    # multiplicarla por 100 (mul(100))
    grupo = data.groupby(x)[y].mean().mul(100).rename('tasa_conv').reset_index()

    # Y generar gráfica
    if type=='line': # Útil para rangos continuos
        plt.figure(figsize=(10,6))
        sns.lineplot(x=var_predictora, y='tasa_conv', data=grupo)
        plt.grid()
    elif type=='bar': # Útil si los datos están divididos en rangos o son categóricos
        plt.figure(figsize=(14,6))
        sns.barplot(x=var_predictora, y='tasa_conv', data=grupo, order=order)
        plt.grid()
    elif type=='scatter': # Útil si los datos están divididos en rangos o son categóricos
        plt.figure(figsize=(10,6)) 
        sns.scatterplot(x=var_predictora, y='tasa_conv', data=grupo)
        plt.grid()

Lo clave del bloque de código anterior es la línea 8, donde usamos el método «groupby» de Pandas para agrupar el dataset por edades, extraer la columna «y» (la tasa de conversión), calcular su promedio y multiplicar el resultado por 100 (para obtener las tasas en escala porcentual).

A continuación simplemente ejecutamos esta función:

graficar_tasas_conversion('age','y_bin')

Con lo cual obtendremos este gráfico que nos muestra el comportamiento detallado de la tasa de conversión con respecto a las diferentes edades de los clientes en nuestro dataset:

Comportamiento de las tasas de conversión (eje vertical) vs. la edad de los clientes en el dataset (eje horizontal)
Comportamiento de las tasas de conversión (eje vertical) vs. la edad de los clientes en el dataset (eje horizontal)

En el gráfico anterior podemos observar que los jóvenes (edades entre 18 y 25) y los adultos mayores (60 o más años) tienen mayor disposición a comprar (es decir tasas de conversión más altas.

Así que podemos profundizar un poco más en esta parte del análisis. Para ello crearemos grupos de edad (18-25, 25-60 y más de 60 años) y usaremos nuevamente la función «graficar_tasas_conversion» pero en modo gráficos de barras para ver en detalle el comportamiento de las tasas de conversión para cada grupo:

# Creación de grupos de edad
data.loc[:,'grupos_edad'] = "18-25"
data.loc[data['age'] > 60, 'grupos_edad'] = ">60"
data.loc[(data['age'] > 25) & (data['age'] <= 60), 'grupos_edad'] = "26-60"

graficar_tasas_conversion('grupos_edad', 'y_bin', type='bar')

Al ejecutar este bloque de código obtendremos un gráfico como este:

Comportamiento de las tasas de conversión (eje vertical) y los rangos de edad definidos (eje horizontal)
Comportamiento de las tasas de conversión (eje vertical) y los rangos de edad definidos (eje horizontal)

¡Y en este caso vemos un patrón bastante claro!, pues los 3 rangos de edad están bastante diferenciados en términos de tasas de conversión: 18-25 años (24%), 26-60 años (11%), más de 60 años (43%)

Así que para nuestro análisis, los rangos de edad resultan mucho más relevantes que la variable edad. Por tanto, eliminaremos esta columna:

data.drop(columns=['age'], inplace=True)

Análisis por saldo (balance)

Para esta parte del análisis podemos aplicar una lógica similar a la usada con la variable edad. Así que crearemos agrupaciones para diferentes rangos de saldos bancarios (saldos negativos, entre 0 y 4K, 4K-16K, 16K-20K y más de 20K) y almacenaremos el resultado en la columna «grupos_balance».

Y después de crear estas categorías podemos aplicar la función «graficar_tasas_conversion» en modo gráfico de dispersión («scatter») a la columna que acabamos de crear. Este sería el código completo:

# Creación de grupos de balance
data.loc[:,'grupos_balance'] = "<0"
data.loc[(data['balance'] >= 0) & (data['balance'] < 4000), 'grupos_balance'] = "0-4K"
data.loc[(data['balance'] >= 4000) & (data['balance'] < 16000), 'grupos_balance'] = "4K-16K"
data.loc[(data['balance'] >= 16000) & (data['balance'] < 20000), 'grupos_balance'] = "16K-20K"
data.loc[data['balance'] >= 20000, 'grupos_balance'] = ">20K"

orden = ['<0', '0-4K', '4K-16K', '16K-20K', '>20K']
graficar_tasas_conversion('grupos_balance', 'y_bin', type='bar', order=orden)

Con lo cual obtenemos un gráfico como este:

Comportamiento de la tasa de conversión (eje vertical) con los diferentes saldos en la cuenta bancaria (eje horizontal)
Comportamiento de la tasa de conversión (eje vertical) con los diferentes saldos en la cuenta bancaria (eje horizontal)

Y en este caso podemos extraer una observación importante: a mayor liquidez, generalmente aumenta la tasa de conversión, excepto en el rango de 16K-20K.

Como los grupos 4K-8K, 8K-12K y 12K-16K tienen tasas de conversión similares, podemos agruparlos en la nueva categoría 4K-16K para facilitar el análisis. Hagamos las agrupaciones y generemos el gráfico de barras correspondiente siguiendo la misma lógica usada hace un momento:

# Nueva columna en el dataset: "grupos_balance"
data.loc[:,'grupos_balance'] = "<0"
data.loc[(data['balance']>=0) & (data['balance']<4000),'grupos_balance'] = "0-4K"
data.loc[(data['balance']>=4000) & (data['balance']<16000),'grupos_balance'] = "4K-16K"
data.loc[(data['balance']>=16000) & (data['balance']<20000),'grupos_balance'] = "16K-20K"
data.loc[data['balance']>=20000,'grupos_balance'] = ">20K"

# Y grafiquemos la tasa de conversión para esta nueva columna
orden = ['<0','0-4K','4K-16K','16K-20K','>20K']
graficar_tasas_conversion('grupos_balance','y_bin',type='bar', order=orden)

Con lo cual obtenemos este gráfico:

Comportamiento de la tasa de conversión (eje vertical) con los diferentes rangos de saldos en la cuenta bancaria (eje horizontal)
Comportamiento de la tasa de conversión (eje vertical) con los diferentes rangos de saldos en la cuenta bancaria (eje horizontal)

Y en este punto podemos usar el método «drop()» para eliminar la columna «balance» que ya no resulta necesaria para nuestro análisis:

data.drop(columns=['balance'], inplace=True)

Análisis de variables categóricas

A continuación la idea es ver si existe algún tipo de relación entre las variables categóricas y la variable tasas de conversión. De nuevo, en este caso aprovecharemos la función «graficar_tasas_conversion» para generar los gráficos que nos permitirán hacer esta parte de la exploración.

Comencemos viendo qué ocurre con la variable «job» (ocupación:

# Tasa de conversión por tipo de trabajo
graficar_tasas_conversion('job', 'y_bin', type='bar')

Tras ejecutar el código anterior podemos observar este comportamiento:

Comportamiento de la tasa de conversión (eje vertical) vs. ocupación (eje horizontal)
Comportamiento de la tasa de conversión (eje vertical) vs. ocupación (eje horizontal)

Aquí destaca que los estudiantes y jubilados tienen las tasas de conversión más altas (28% y 23% respectivamente). Así que la ocupación podría ser una variable predictora.

Veamos qué ocurre con la variable «marital» (estado civil):

graficar_tasas_conversion('marital','y_bin',type='bar')

Este es el gráfico resultante:

Comportamiento de las tasas de conversión vs. el estado civil
Comportamiento de las tasas de conversión vs. el estado civil

En este caso observamos que las tasas de conversión son muy similares para los diferentes niveles en la variable «marital». Así que esta parece no tener un gran efecto en las tasas de conversión.

A continuación analizaremos la variable «education» (nivel educativo):

graficar_tasas_conversion('education','y_bin',type='bar')

En este caso vemos este comportamiento:

Comportamiento de las tasas de conversión vs. el nivel educativo
Comportamiento de las tasas de conversión vs. el nivel educativo

Con este gráfico podemos ver que hay un ligero incremento en la tasa de conversión a medida que aumenta el nivel educativo, lo cual tiene lógica pues es de esperar que a mayor nivel educativo mayor sea el nivel de ingreso de las personas (lo cual redunda en mayores tasas de conversión). Así que en este caso podemos considerar que la variable «education» es una variable predictora.

Veamos ahora qué ocurre con la columna «default» (si la persona dejó o no de pagar sus obligaciones financieras):

graficar_tasas_conversion('default','y_bin',type='bar')

Este es el resultado de ejecutar el código anterior:

Comportamiento de las tasas de conversión vs. "default"
Comportamiento de las tasas de conversión vs. «default»

Para esta variable podemos observar que las tasas de conversión para quienes no tienen «default» son de casi el doble para quienes sí lo tienen (12% vs. 6% aproximadamente). Es decir que «default» es una variable relevante pues afecta las tasas de conversión.

Veamos ahora la variable «housing» (si la persona posee o no crédito hipotecario):

graficar_tasas_conversion('housing','y_bin',type='bar')

Este es el comportamiento de las tasas de conversión para esta variable:

Comportamiento de las tasas de conversión vs. la variable "housing" (si la persona posee o no vivienda propia)
Comportamiento de las tasas de conversión vs. la variable «housing» (si la persona posee o no crédito hipotecario)

Acá es evidente que quienes no tienen crédito hipotecario («housing»=no) definitivamente tienen mayores tasas de conversión. Así que concluimos que ésta es una variable predictora.

Vamos ahora con la variable «loan» (si la persona tiene o no créditos con entidades bancarias):

graficar_tasas_conversion('loan','y_bin',type='bar')

Veamos cómo se comportan las tasas de conversión:

Comportamiento de las tasas de conversión vs. créditos (si la persona tiene o no préstamos de consumo)
Comportamiento de las tasas de conversión vs. créditos (si la persona tiene o no préstamos de consumo)

En este caso de la variable «loan» ocurre algo similar a la variable «housing» analizada anteriormente: quienes no tienen créditos de consumo presentan definitivamente mayores tasas de conversión. Así que «loan» también es una variable predictora.

Finalmente, veamos qué ocurre con la variable «poutcome» (el resultado de la campaña de marketing anterior):

graficar_tasas_conversion('poutcome','y_bin',type='bar')

Veamos si existen variaciones de las tasas de conversión con los diferentes niveles en la variable «poutcome»:

Comportamiento de las tasas de conversión vs. la variable "poutcome" (el resultado de la campaña anterior)
Comportamiento de las tasas de conversión vs. la variable «poutcome» (el resultado de la campaña anterior)

Y acá vemos que el efecto de esta variable «poutcome» es bastante significativo en las tasas de conversión, pues por ejemplo si el resultado de la campaña anterior fue un éxito («success»), la probabilidad de conversión actual es cercana al 70%.

Así que una vez culminado este análisis univariado, podemos hacer un resumen de los hallazgos más importantes. En particular, podemos decir que las variables predictoras con mayor impacto en la tasa de conversión parecen ser, en orden de importancia:

  1. poutcome: casi 70% de conversión para el nivel «success»
  2. job: con tasas de 22% y 28% para ‘retired’ y ‘student’
  3. grupos_balance y grupos_edad, con tasas de conversión cercanas al 16% para varios intervalos
  4. default, housing y loan con tasas de conversión entre 12% y 16% para los niveles «no»
  5. marital y education, con niveles de conversión comparables con default, housing y loan.

Fase 3: Análisis Bivariado

Otra etapa importantísima en el Análisis Exploratorio de Datos es el análisis bivariado, que nos permite determinar cómo interactúan dos variables predictoras, en este caso con respecto a la tasa conversión.

Así que crearemos una función para realizar este análisis bivariado usando gráficos de puntos:

def graficar_tc_bivariada(col_list):
  tc = data.groupby(col_list)['y_bin'].mean().to_frame().reset_index()

  # Gráfica
  plt.figure(figsize=(13,7))
  ax = sns.pointplot(x=tc['y_bin'], y=tc[col_list[0]], hue=tc[col_list[1]], join=False)
  ax.yaxis.grid(True)
  ax.xaxis.grid(True)
  plt.title(f'Tasa de conversión para {col_list[0]} y {col_list[1]}')
  plt.xlabel('Tasa de conversión (%)')
  plt.xlim((0,1));

Desglosemos los principales elementos de esta función:

  • A la entrada (línea 1) presentamos a la función el listado de columnas («col_list») que contendrá el par de variables a analizar
  • En la línea 2 agrupamos el set de datos usando como criterio las dos variables a analizar, extraemos la columna «y_bin» (tasas de conversión) y calculamos el promedio resultante. Con esto tendremos el valor promedio de las tasas de conversión para cada una de las variables a comparar
  • En la línea 6 hacemos el gráfico de puntos («pointplot») ubicando la tasa de conversión en el eje horizontal (x), la primera variable a analizar en el eje vertical (y) y codificando la segunda variable con un color («hue=tc[col_list[1]]»)

Así que ahora tomaremos pares de las variables más relevantes identificadas en el análisis univariado («poutcome», «job» y «grupos_balance») y obtendremos los gráficos de puntos incluyendo en todos los casos la variable «poutcome» (que resultó ser la más relevante según lo observado en el análisis univariado).

Interacción «job» y «poutcome»

graficar_tc_bivariada(['job','poutcome'])

Este es el gráfico de puntos que obtenemos para estas variables:

Análisis bivariado: comportamiento de la tasa de conversión con respecto a las variables "job" (ocupación) y "poutcome" (resultado de la campaña anterior)
Análisis bivariado: comportamiento de la tasa de conversión con respecto a las variables «job» (ocupación) y «poutcome» (resultado de la campaña anterior)

¡Y acá vemos un patrón bastante claro!. Los puntos de color verde son el resultado de combinar «poutcome = success» con diferentes tipos de ocupación. Y en particular, al combinar «poutcome» con ocupaciones como administrativos, jubilados, servicios, estudiantes o desempleados, se pueden alcanzar tasas de conversión mayores o iguales al 70%.

Interacción «grupos_balance» y «poutcome»

graficar_tc_bivariada(['grupos_balance', 'poutcome'])

En este caso vemos el siguiente comportamiento:

Análisis bivariado: comportamiento de la tasa de conversión con respecto a las variables "grupos_balance" (saldo en la cuenta bancaria) y "poutcome" (resultado de la campaña anterior)
Análisis bivariado: comportamiento de la tasa de conversión con respecto a las variables «grupos_balance» (saldo en la cuenta bancaria) y «poutcome» (resultado de la campaña anterior)

Acá es interesante observar que personas con saldos entre 16K y 20K que tuvieron éxito en la campaña anterior («poutcome=success») tienen una conversión del 100%.


El perfil ideal del cliente

Así que con este Análisis Exploratorio de Datos, y tomando como base todas las observaciones que hemos realizado a lo largo de este tutorial, podemos concluir que el perfil con mayor potencial de conversión para el banco cumple con las siguientes características:

  1. Antecedentes: El factor más determinante es haber aceptado un producto en la campaña anterior (poutcome == success).
  2. Ocupación: estudiantes, jubilados y desempleados muestran mayor interés.
  3. Liquidez: clientes con saldos relativamente altos (especialmente entre 16K y 20K euros).
  4. Edad: Personas en los extremos de la distribución (18-25 años o mayores de 60).
  5. Carga Financiera: Clientes que no tienen créditos hipotecarios, de consumo, ni deudas en mora (default == no).

Es posible que la combinación de más de dos variables (análisis multivariado) arroje más luces sobre estos perfiles. Pero en este caso la interpretación de los resultados se dificulta a medida que analizamos de manera simultánea más y más variables.

El código fuente y el set de datos de este tutorial

▼ El código fuente de este tutorial

▼ El set de datos de este tutorial

Conclusión

Muy bien, en este tutorial hemos visto un ejemplo detallado de buena parte los elementos que usualmente estarán presentes al momento de realizar el Análisis Exploratorio de un set de datos tabular.

En últimas, este análisis siempre estará guiado por la pregunta de negocio que queremos responder. E idealmente, los hallazgos de este análisis deberían permitirnos responder a esa pregunta.

Sin embargo, a pesar de lo visto en este tutorial, es importante tener en cuenta que cada análisis exploratorio es único pues en últimas dependerá de las particularidades del negocio y de los datos que hayamos recolectado. Así que la idea es que con este tutorial tengas las bases para desarrollar un análisis exploratorio de tus propios datos.

Si te interesa ver en detalle las diferentes técnicas que podemos usar al momento de desarrollar el análisis exploratorio de datos, te invito a darle una mirada al curso de Estadística Descriptiva acá en la Academia Online, donde vemos precisamente de forma aplicada las principales herramientas para el desarrollo de este análisis y que podrás aplicar en tus proyectos de Ciencia de Datos.

© Codificando Bits, LLC | Blog | Contacto | Servicios | Acerca de | Políticas

¿Has olvidado la contraseña?
¿Has perdido tu contraseña? Por favor, introduce tu nombre de usuario o dirección de correo electrónico. Recibirás por correo electrónico un enlace para crear una nueva contraseña.
body::-webkit-scrollbar { width: 7px; } body::-webkit-scrollbar-track { border-radius: 10px; background: #f0f0f0; } body::-webkit-scrollbar-thumb { border-radius: 50px; background: #dfdbdb }