#!/usr/bin/env python
# coding: utf-8
# .
#
#

#
Conversion Rate Optimization For E-COMMERCE
#
#
#
# Table of Contents
#
#
# Introducción
#
# En este proyecto se aborda el caso de un comercio tipo ecommerce que presenta estancamiento en sus ventas. Se aplicaran técnicas analíticas a los registros transaccionales con el fin de obtener lineas de accion para el diseño de una estrategia basada en datos. Al final del preoyecto, se entregan resultados de diagnóstico en las áreas analizadas, seguido de las acciones estratégicas de resolución para incrementar el CRO.
#
#
# # **Objetivos del Proyecto**
#
#
# Impulsar el crecimieno en ventas del E-Commerce por medio de:
#
# * Analizar situación actual en base a tres áreas de enfoque: Ventas, Clientes y Productos.(Establecer el baseline).
#
# * Determinar las mejores estrategias de CRO (Conversion Rate Optimization) adecuadas en base a los datos obtenidos.
#
#
# # Procesos ETL.
#
#
# **Herramientas:**
# El proyecto se aborda implementando Python por medio de Jupyter notebook, con los siguientes paquetes: Pandas, Numpy, Matplotlib, Scipy, Plotly, Seaborn y SqlAlchemy.
#
# **Data Set:**
# La empresa cuenta con una base de datos SQL Server desde donde administra toda su información transaccional.
#
#
# ## Importación de librerias.
# In[1]:
# Se importan los pquetes requeridos
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
import seaborn as sns
import sqlalchemy as sa
#Automcompletar rápido
get_ipython().run_line_magic('config', 'IPCompleter.greedy=True')
#Formato de display
pd.options.display.float_format = '{:15.2f}'.format
#Estilo de sns
sns.set_theme(style="whitegrid")
# ## Conexión a base de datos.
# In[2]:
# Conexión a la base de datos y carga de los datos iniciales.
con = sa.create_engine('sqlite:///../Datos/ecommerce.db')
# In[3]:
# Inspeccion de tablas existentes.
from sqlalchemy import inspect
insp = inspect(con)
tablas = insp.get_table_names()
tablas
# In[4]:
# Creando df a partir de las tablas.
oct = pd.read_sql('2019-Oct', con)
nov = pd.read_sql('2019-Nov', con)
dic = pd.read_sql('2019-Dec', con)
ene = pd.read_sql('2020-Jan', con)
feb = pd.read_sql('2020-Feb', con)
# In[5]:
# integración de tablas y datos en un único DataFrame
df = pd.concat([oct,nov,dic,ene,feb], axis = 0)
df
# ## Calidad de Datos:
# In[6]:
# Tipos de Variables
df.info()
# In[7]:
# Eliminar la columna Index
df.drop(columns = 'index', inplace = True)
# In[8]:
# Corregir tipo de datos. pasar event_time a datetime
def datetime_rapido(dt,formato):
def divide_fecha(fecha):
division = fecha.split()
date = division[0]
time = division[1]
cadena = date + ' ' + time
return cadena
resultado = pd.to_datetime(dt.apply(lambda x: divide_fecha(x)), format = formato)
return resultado
# In[9]:
# llamando a la función y mostando cambios
formato = '%Y-%m-%d %H:%M:%S'
df.event_time = datetime_rapido(df.event_time,formato)
df.info()
# In[10]:
# Renombramos las variables a español
df.columns = ['fecha',
'evento',
'producto',
'categoria',
'categoria_cod',
'marca',
'precio',
'usuario',
'sesion']
# In[11]:
# Análisis de nulos
df.isna().sum().sort_values(ascending = False)
#
#
# **Summary:**
#
# * categoria_cod tiene casi todos los registros a nulo
# * marca tiene casi la mitad de los registros a nulo
# * hay 500 nulos en sesión
#
# Acciones:
#
# * eliminar las variables categoria_cod y marca
# * eliminar los nulos de sesión ya que es una variable relevante
#
#
# In[12]:
df = df.drop(columns = ['categoria_cod','marca']).dropna()
# In[13]:
# Seleccion de variables con precio positivo
df = df[df.precio > 0]
df
# In[14]:
# Cantidad de eventos
df.evento.nunique()
# In[15]:
# Frcuencia de eventos
df.evento.value_counts()
# In[16]:
# Cantidad de prodctos distintos.
df.producto.nunique()
# In[17]:
# Cantidad de categorias de producto.
df.categoria.nunique()
# In[18]:
#Asignando la fecha como indice
df.set_index('fecha', inplace = True)
# * **TRANSFORMACION DE DATOS**
# * Creando 3 nuevas variables a partir de la fecha
# In[19]:
# Funcion para segmentar dateTime
def componentes_fecha(dataframe):
date = dataframe.index.date
año = dataframe.index.year
mes = dataframe.index.month
dia = dataframe.index.day
hora = dataframe.index.hour
minuto = dataframe.index.minute
segundo = dataframe.index.second
return(pd.DataFrame({'date':date, 'año':año,'mes':mes, 'dia':dia, 'hora':hora, 'minuto':minuto, 'segundo':segundo}))
# In[20]:
# LLamando a la funcion y creando nuevo df
df = pd.concat([df.reset_index(),componentes_fecha(df)], axis = 1).set_index('fecha')
df
# In[21]:
# Indicadores exógenos de feriados importantes.
df['black_friday'] = 0
df.loc['2019-11-29','black_friday'] = 1
df['san_valentin'] = 0
df.loc['2020-02-14','san_valentin'] = 1
# In[22]:
# Tablón Analitico final
df.head()
#
# # Procesos EDA
# ## Analizando las ventas:
# In[23]:
# Frecuencia de eventos
eventos = df.evento.value_counts()
eventos
# In[24]:
# Generación de kpi Customer Journey
kpi_visualizaciones_p = 100
kpi_carrito_p = eventos.loc['cart'] / eventos.loc['view'] * 100
kpi_abandono_p = eventos.loc['remove_from_cart'] / eventos.loc['cart'] * 100
kpi_compra_p = eventos.loc['purchase'] / eventos.loc['cart'] * 100
kpis = pd.DataFrame({'kpi':['visitas','carrito','compra'],
'valor':[kpi_visualizaciones_p,kpi_carrito_p,kpi_compra_p]})
kpis
# In[25]:
# Visualizando el embudo de Ventas
from plotly import graph_objects as go
fig = go.Figure(go.Funnel(
y = kpis.kpi,
x = kpis.valor.round(2),
marker = {'color': ['red','blue','green']},
opacity = 0.3
))
fig.update_layout(
title = 'Funnel Conversión Inicial')
fig.show()
#
# Conclusiones:
#
# * Las tasas de partida son un 60% de carrito sobre visualiazaciones y un 22% de compra sobre carrito
# * Por tanto, existe un **40% de visitas** sobre las que hay que trabajar para conseguir más carritos, y un **78% de carritos** sobre los que trabajar para conseguir más compras
# In[26]:
# generando dataframe agregado para analizar sesiones.
sesion_prod = df.groupby(['sesion','evento']).producto.count()
sesion_prod = sesion_prod.unstack().fillna(0)
sesion_prod = sesion_prod[['view','cart','remove_from_cart','purchase']]
# In[27]:
# media de cada evento por sesión
media_eventos_sesion = sesion_prod.mean()
media_eventos_sesion
#
# Conclusión:
#
# En cada sesión, de media:
#
# * Se ven 2.2 productos
# * Se añaden 1.3 productos al carrito
# * Se eliminan 0.9 productos del carrito
# * Se compran 0.3 productos
#
# **Estos números representan el objetivo de las acciones de CRO para lograr los incrementos.**
# In[28]:
# generando dataframe agregado para analizar sesiones.
eventos_hora = df.groupby(['evento','hora']).producto.count()
eventos_hora = eventos_hora.unstack(level = 0)
# In[29]:
# crear una nueva variable que sea el ratio de compras por visita en cada hora.
eventos_hora['compras_visitas'] = eventos_hora.purchase / eventos_hora.view * 100
eventos_hora = eventos_hora[['view','cart','remove_from_cart','purchase','compras_visitas']]
# In[30]:
# Analizamos los horarios de compra.
plt.figure(figsize = (10,4))
sns.lineplot(data = eventos_hora, x = eventos_hora.index, y = 'compras_visitas')
plt.xticks(eventos_hora.index);
# In[31]:
# titpificar variables para unificar escalas y generar mapa de calor por hora
def tipificar(variable):
media = variable.mean()
dt = variable.std()
return(variable.apply(lambda x: (x - media) / dt))
# In[32]:
# llamando a la función
eventos_hora_tip = eventos_hora.apply(tipificar)
# In[33]:
# Mapa de calor agregado por eventos en cada horario
plt.figure(figsize = (12,12))
sns.heatmap(data = eventos_hora_tip);
#
#
# **INSIGHT #1**: Todas las métricas se maximizan en las franjas entre las 9:00 y las 13:00 y entre las 18:00 y las 20:00
# * Esta info es muy relevante, por ejemplo, de cara a paid ads, tanto de generación de tráfico como de retargeting.
# * Además, parece haber algún segmento de clientes que compra a la 01:00 am, que aunque no sea muy frecuente, compra mucho.
#
#
# In[34]:
# Media de facturacion mensual
df.loc[df.evento == 'purchase'].groupby('mes').precio.sum().mean()
# **Esta variable es importante porque representa el ticket medio por mes (125000 $), el cual será nuestro barómetro de crecimiento.**
#
#
# In[35]:
# Analizando la tendencia de facturacion mensual
tendencia = df.groupby('evento').resample('W').evento.count().unstack(level = 0)
tendencia = tendencia[['view','cart','remove_from_cart','purchase']]
tendencia.plot(subplots = True, figsize = (12,6), sharex = True, xticks = tendencia.index, x_compat=True, rot = 90);
#
#
# **INSIGHT #2:** La gran conclusión es que todo el pastel de las compras navideñas se reparte en la semana del black friday
# * La tendencia es plana en todas las métricas, lo que confirma la necesidad de las acciones de CRO.
# * hay un pico muy pronunciado el 27 de Enero, seguramente algún evento local
#
#
# ## Analizando a los Clientes:
# In[36]:
# Creando un df agregado por clientes y 3 variables importantes.
clientes = df.loc[df.evento == 'purchase'].groupby(['usuario']).agg({'producto':'count',
'sesion':'nunique',
'precio': 'mean',
'date': 'max'})
clientes.columns = ['productos_tot_num','compras_tot_num','precio_medio_prod','ult_compra']
# In[37]:
# Generando 2 nuevas variables
clientes['gasto_tot'] = clientes.productos_tot_num * clientes.precio_medio_prod
clientes['productos_por_compra'] = clientes.productos_tot_num / clientes.compras_tot_num
clientes
# In[38]:
# analizando la distribucion de clientes en cuanto a gasto
sns.histplot(data = clientes, x = 'gasto_tot', bins = 50)
plt.xlim([0,300]);
# La gran mayoría de los clientes han gastado menos de 50€ en el período.
# In[39]:
# Analizando clientes por su frecuencia de compra.
sns.countplot(data = clientes, x = 'compras_tot_num');
#
#
# **INSIGHT #3:** La gran mayoría de los clientes sólo hace una compra.
#
# Existe gran recorrido para mejorar este ratio mediante:
#
# * email marketing con newletters y ofertas personalizadas
#
#
# In[40]:
# Analizando clientes por cantidad de productos en cada compra.
clientes.productos_por_compra.describe()
#
#
# **INSIGHT #4:** La compra mediana incluye 5 productos.
#
# Pero un 25% de los clientes compran más de 10 productos en la misma compra.
#
# Existe gran recorrido para mejorar este ratio mediante:
#
# * sistemas de recomendación en el momento de la compra
#
#
# In[41]:
# Analizando clientes por gasto total medio
clientes.gasto_tot.describe()
#
#
# **INSIGHT #5:** Existen clientes con gasto medio bastante alto, hasta decenas de veces superior a la media. Representan al segmento de alta facturación.
#
# Se sugiere atraer a estos clientes mediante programas de fidelización.
#
#
# ## Analizando a los Productos:
# In[42]:
# Creando un df agregado a nivel de productos
prod = df.groupby(['producto','evento']).size()
prod = prod.unstack(level = 1).fillna(0)
# In[43]:
# Se crea una matriz de precios para hacer join con el df, y se reordena.
maestro_precios = df.groupby('producto', as_index = False).precio.mean()
prod = pd.merge(left = prod, right = maestro_precios, how = 'left', on = 'producto')
prod = prod[['producto','view','cart','remove_from_cart','purchase','precio']]
prod
# In[44]:
# produtos que no se venden
prod[prod.purchase == 0]
#
#
# **INSIGHT #6:** Casi la mitad de los productos no han tenido ninguna venta en los 5 meses del histórico.
#
# * ¿No se ven?
# * ¿Se ven pero no se compran?
# * ¿Es porque se sustituyen por otros productos propios?
# * ¿Es porque se venden a precios mas bajos en la competencia?
# * Etc
#
# Se podrían eliminar del catálogo, o como mínimo de la tienda, newsletter, etc, para que no ocupen espacio de los productos que sí se venden.
#
#
# In[45]:
# Analizando la relación entre precio y volumen de ventas de los productos.
# Ya que este análisis incluye las ventas vamos a eliminar los productos que no han tenido ninguna.
sns.scatterplot(data = prod[prod.purchase > 0], x = 'precio', y = 'purchase', hue = 'precio');
# **Sí que existe una clara relación decreciente.**
# In[46]:
# analizando 20 de los productos mas vistos
prod.view.sort_values(ascending = False)[0:20].plot.bar();
#
#
# Es posible **incrementar las ventas y el ticket medio destacando estos productos en la tienda** Siempre que además de ser vistos también se vendan.
#
#
# In[47]:
# Analizando productos muy vistos y poco comprados
# Por ejemplo productos que miran muchos clientes pero que luego no los compran.
sns.scatterplot(data = prod, x = 'view', y = 'purchase');
# In[48]:
# quitando el atípico y haciendo zoom en la ventana de muchas vistas pocas compras.
sns.scatterplot(data = prod.loc[prod.view < 4000], x = 'view', y = 'purchase', hue = 'precio')
plt.xlim(1000,3000)
plt.ylim(0,150);
# **Hay una oportunidad con estos productos,** porque por algún motivo generan el interés de los clientes, pero finalmente no los compran.
#
# # Conclusiones:
#
#
# La tendencia actual es plana en todas las métricas, lo que confirma la necesidad de las acciones de CRO (Conversion Rate Optimization).
#
# Tras el análisis realizado sobre los datos transaccionales, se ha desarrollado un plan CRO de 8 iniciativas concretas, organizadas en 5 grandes palancas o áreas de negocio que, con alta probabilidad y de acuerdo a los datos ahora conocidos, van a impulsar los baselines, consiguiendo un incremento global de los ingresos del ecommerce. **Los datos trazan el camino mas eficiente para obtener resultados ganadores.**
#
#
# ## Baseline
#
#
# Los resultados analiticos indican que el Ecommerce presenta los siguientes **valores promedio por cada sesión:**
#
# * KPIs por sesión: Se ven 2.2 productos
# * KPIs por sesión: Se añaden 1.3 productos al carrito
# * KPIs por sesión: Se eliminan 0.9 productos del carrito
# * KPIs por sesión: Se compran 0.3 productos
#
# * Venta cruzada: mediana de 5 productos por compra
#
# * Recurrencia: el 10% de los clientes vuelve a comprar tras el primer mes
#
# * Conversión: 60% de añadir al carrito sobre visualizaciones
# * Conversión: 22% de compra sobre añadidos a carrito
# * Conversión: 13% de compra sobre visualizaciones
#
# * Facturación media mensual: 125.000€
#
#
# ## Acciones de incremento de visualizaciones
#
#
# 1. Revisar las campañas de paid (generación y retargeting) para concentrar la inversión en franjas entre las 9 y las 13 y entre las 18 y las 20
# 2. Concentrar la inversión del período navideño y post-navideño en la semana del black friday
#
#
# ## Acciones de incremento de conversión
#
#
# 3. Preconfigurar la home con los productos identificados en los análisis most viewed y most sold.
# 4. Trabajar sobre los productos muy vistos pero poco comprados
#
#
# ## Acciones de incremento de venta cruzada
#
#
# 5. La compra mediana incluye 5 productos. Incrementar este ratio mediante la implementación en tiempo real de un sistema de recomendación.
#
#
# ## Acciones de incremento de frecuencia de compra
#
#
# El 90% de los clientes sólo hace una compra.
#
# 6. Crear una newsletter periódica en base aun sistema de recomendación para incrementar la frecuencia de visita
# 7. Campañas promocionales sobre los segmentos top de la cartera de clientes.
#
#
# ## Acciones de fidelización de clientes
#
#
# 8. Crear un programa de fidelización sobre los segmentos top de la cartera de clientes.
#
#
# # Business Case
#
#
# Es recomendable en este caso, **generar un BUSINESS CASE** para observar:
#
# 1. las 8 acciones de CRO recomendadas dentro de un plan.
# 2. Los Presupuestos, proyecciones y escenarios de rentabilidad.
#
#
#
# # Consideraciones finales:
#
# Este proyecto es experimental, pero se basa en un enfoque bastante realista. Los datos para este proyecto se obtienen de Kaggle, un sitio web que ofrece conjuntos de datos experimentales. Puedes encontrarlos en https://www.kaggle.com/datasets
# .
#
#
# .