# A veces necesitamos instalar nuevas librerías en nuestros proyectos
!pip install openpyxl==3.0.10
Collecting openpyxl==3.0.10
Downloading openpyxl-3.0.10-py2.py3-none-any.whl (242 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 242.1/242.1 KB 21.8 MB/s eta 0:00:00
Collecting et-xmlfile
Downloading et_xmlfile-1.1.0-py3-none-any.whl (4.7 kB)
Installing collected packages: et-xmlfile, openpyxl
Successfully installed et-xmlfile-1.1.0 openpyxl-3.0.10
WARNING: You are using pip version 22.0.4; however, version 22.1.2 is available.
You should consider upgrading via the '/root/venv/bin/python -m pip install --upgrade pip' command.
# imports
import numpy as np
import pandas as pd
import sqlite3 as sql3
import openpyxl # para que levante bien el excel
import matplotlib.pyplot as plt
import seaborn as sns
# Levanto los datos en 3 diferentes dataframes
# Artículos
conn = sql3.connect('/work/data/articles.db')
sql_query = pd.read_sql_query('SELECT * FROM articles', conn)
df_articles = pd.DataFrame(sql_query, columns = ['article_id', 'article_name', 'unit_price'])
# Vendedores
df_sellers = pd.read_excel('/work/data/sellers.xlsx', index_col=0)
# Órdenes
df_orders = pd.read_csv('/work/data/orders.csv')
# Exploración del df de artículos
print('Muestra de datos')
print(df_articles.head())
print('\nFormato del dataframe')
print(df_articles.shape)
print('\nBúsqueda de valores nulos por columna')
print(df_articles.isnull().sum())
print('\nFormato de los datos por columna')
print(df_articles.dtypes)
df_articles
Muestra de datos
article_id article_name unit_price
0 20015 Smartphone 525.00
1 20016 Full Pc 2127.81
2 20017 Monitor 230.00
3 20018 Tablet 130.00
4 20019 Desk 130.10
Formato del dataframe
(31, 3)
Búsqueda de valores nulos por columna
article_id 0
article_name 0
unit_price 0
dtype: int64
Formato de los datos por columna
article_id int64
article_name object
unit_price object
dtype: object
article_idint64
20015 - 20045
article_nameobject
Smartphone3.2%
Full Pc3.2%
29 others93.5%
0
20015
Smartphone
1
20016
Full Pc
2
20017
Monitor
3
20018
Tablet
4
20019
Desk
5
20020
Chair
6
20021
Modem
7
20022
Range Extender
8
20023
Notebook
9
20024
Netbook
# Exploración del df de vendedores
print('Muestra de datos')
print(df_sellers.head())
print('\nFormato del dataframe')
print(df_sellers.shape)
print('\nBúsqueda de valores nulos por columna')
print(df_sellers.isnull().sum())
print('\nFormato de los datos por columna')
print(df_sellers.dtypes)
df_sellers
Muestra de datos
seller_name
seller_id
1 Aveline Swanwick
2 Jase Doy
3 Oliviero Charkham
4 Cornie Wynrehame
5 Ewell Peres
Formato del dataframe
(15, 1)
Búsqueda de valores nulos por columna
seller_name 0
dtype: int64
Formato de los datos por columna
seller_name object
dtype: object
seller_nameobject
Aveline Swanwick6.7%
Jase Doy6.7%
13 others86.7%
1
Aveline Swanwick
2
Jase Doy
3
Oliviero Charkham
4
Cornie Wynrehame
5
Ewell Peres
6
Milly Christoffe
7
Kati Innot
8
Tobin Roselli
9
Onida Cosely
10
Cirilo Grandham
# Exploración del df de órdenes
print('Muestra de datos')
print(df_orders.head())
print('\nFormato del dataframe')
print(df_orders.shape)
print('\nBúsqueda de valores nulos por columna')
print(df_orders.isnull().sum())
print('\nFormato de los datos por columna')
print(df_orders.dtypes)
df_orders
Muestra de datos
order_id week article_id quantity seller_id country_name
0 15024 1 20039 10 10 Peru
1 15025 1 20029 15 5 Peru
2 15026 1 20024 5 14 Bolivia
3 15027 1 20018 9 14 Brazil
4 15028 1 20035 6 15 Mexico
Formato del dataframe
(1000, 6)
Búsqueda de valores nulos por columna
order_id 0
week 0
article_id 0
quantity 0
seller_id 0
country_name 0
dtype: int64
Formato de los datos por columna
order_id int64
week int64
article_id int64
quantity int64
seller_id int64
country_name object
dtype: object
order_idint64
15024 - 16023
weekint64
1 - 4
0
15024
1
1
15025
1
2
15026
1
3
15027
1
4
15028
1
5
15029
1
6
15030
1
7
15031
1
8
15032
1
9
15033
1
df_articles['unit_price'] = df_articles['unit_price'].astype(float)
print(df_articles.dtypes)
article_id int64
article_name object
unit_price float64
dtype: object
# Creo una copia del df_orders
my_df = df_orders.copy()
# Cambio el índice del df de artículos
df_articles.set_index('article_id',inplace = True)
# Agrego algunas columnas y pongo el campo que me va a servir de "ancla" para acordarme
my_df = my_df.assign(article_name = my_df['article_id'])
my_df = my_df.assign(total_amount = my_df['article_id'])
my_df = my_df.assign(seller_name = my_df['seller_id'])
# reemplazo los valores en el nuevo df
# 1. busco el nombre del artículo y lo asigno a una variable
# como df_articles está indexado por article_id, lo uso para ubicarme en
# el registro que busco
# SINTAXIS: df_articles.loc[indice][columna]
# [indice] va a ser el dato que obtengo de my_df.loc[i]['article_id']
# -> o sea, tomo registro a registro el article_id y lo uso para extraer
# el nombre del artículo
for i in range(len(my_df.index)): # len(my_df.index) devuelve la cantidad de registros
idArticulo = my_df.loc[i]['article_id']
nombreArticulo = df_articles.loc[idArticulo]['article_name']
# se lo asigno a la columna correspondiente
my_df.loc[i,'article_name'] = nombreArticulo
# hago lo mismo para la columna de total_amount
precioArticulo = df_articles.loc[idArticulo]['unit_price']
cantArticulo = my_df.loc[i]['quantity']
my_df.loc[i,'total_amount'] = precioArticulo * cantArticulo
# columna de seller_name
idVendedor = my_df.loc[i]['seller_id']
nombreVendedor = df_sellers.loc[idVendedor]['seller_name']
my_df.loc[i,'seller_name'] = nombreVendedor
# elimino las columnas que no necesito
my_df.drop(['order_id', 'article_id', 'seller_id'], axis = 'columns', inplace=True)
my_df
weekint64
1 - 4
quantityint64
1 - 15
0
1
10
1
1
15
2
1
5
3
1
9
4
1
6
5
1
6
6
1
13
7
1
14
8
1
7
9
1
4
# RESOLUCIÓN ANALÍTICA
my_df1=my_df.groupby('article_name').sum().sort_values('quantity', ascending=False).head(5)
print(my_df1['quantity'].head(1))
article_name
HDD 413
Name: quantity, dtype: int64
# RESOLUCIÓN GRÁFICA
plot = sns.barplot(y=my_df1.index, x=my_df1['quantity'], palette='mako')
plt.suptitle('Los 5 productos más vendidos (en unidades)', fontsize='xx-large')
for pos in ['right', 'top', 'bottom', 'left']:
plt.gca().spines[pos].set_visible(False)
for i in plot.containers:
plot.bar_label(i, padding=5)
plt.xlabel('')
plt.xticks([])
plt.ylabel(ylabel='')
plt.show()
# RESOLUCIÓN ANALÍTICA
my_df2 = (my_df.groupby(by='article_name').sum()).sort_values('total_amount',ascending=False).head(5)
print(my_df2['total_amount'])
article_name
Full Pc 538335.93
Notebook 251000.00
Smartphone 152250.00
Chair 69477.48
Tablet 48620.00
Name: total_amount, dtype: float64
# RESOLUCIÓN GRÁFICA:
sns.barplot(y=my_df2['total_amount'], x=my_df2.index, palette='mako')
plt.suptitle('Los 5 productos más rentables',fontsize='xx-large')
for pos in ['right', 'top', 'bottom', 'left']:
plt.gca().spines[pos].set_visible(False)
ingresos = my_df2['total_amount'].values
for i, ingreso in enumerate(ingresos):
v = '$ ' + str(int(ingreso))
plt.text(s=v, x=i, y=my_df2['total_amount'][i] + 15000, ha='center')
plt.xlabel('')
plt.yticks([])
plt.ylabel(ylabel='')
plt.show()
# RESOLUCIÓN ANALÍTICA
my_df3 = (my_df.groupby(by='seller_name').sum()).sort_values('total_amount',ascending=False)
print(my_df3[['quantity']+['total_amount']])
quantity total_amount
seller_name
Janel O'Curran 703 192832.47
Brockie Patience 441 142709.88
Oliviero Charkham 555 141329.76
Vasily Danilyuk 521 129157.55
Daisie Slograve 554 120520.11
Aveline Swanwick 629 118874.33
Arnold Kilkenny 583 94552.04
Kati Innot 512 83704.62
Jase Doy 582 80628.31
Ewell Peres 496 78144.32
Onida Cosely 535 77373.37
Milly Christoffe 442 61733.69
Tobin Roselli 519 56984.42
Cornie Wynrehame 523 52253.57
Cirilo Grandham 470 45009.40
# RESOLUCIÓN GRÁFICA
e = [0.2]
exp = [e.append(0) for x in range(len(my_df3)-1)]
c = sns.color_palette('mako', n_colors=len(my_df3))
plt.suptitle(t='Representación de ventas por vendedor', y=1.2, fontsize='xx-large')
_, _, autotexts = plt.pie(my_df3['total_amount'], explode=e,labels=my_df3.index, colors=c,radius=1.7,
autopct='%1.1f%%')
for ins in autotexts:
ins.set_color('white')
plt.show()
# RESOLUCIÓN ANALÍTICA
my_df4 = (my_df.groupby(by='week').sum()).sort_values('total_amount',ascending=False)
print(my_df4['total_amount'])
week
1 507458.81
2 415364.44
3 329140.03
4 223844.56
Name: total_amount, dtype: float64
# RESOLUCIÓN GRÁFICA
sns.barplot(y=my_df4['total_amount'], x=my_df4.index, palette='mako')
plt.suptitle('Variación de ventas', fontsize='xx-large')
for pos in ['right', 'top', 'bottom', 'left']:
plt.gca().spines[pos].set_visible(False)
ingresos = my_df4['total_amount'].values
for i, ingreso in enumerate(ingresos):
v = '$ ' + str(int(ingreso))
plt.text(s=v, x=i, y=my_df4['total_amount'][i+1] + 15000, ha='center')
plt.xlabel('Semanas')
plt.yticks([])
plt.ylabel(ylabel='')
plt.show()
# RESOLUCIÓN ANALÍTICA
my_df5 = (my_df.groupby(by='country_name').sum()).sort_values('total_amount',ascending=False).head(5)
print(my_df5['total_amount'])
country_name
Brazil 441271.85
Argentina 205832.78
Colombia 177514.29
Peru 161421.12
Mexico 138619.99
Name: total_amount, dtype: float64
# RESOLUCIÓN GRÁFICA
sns.barplot(y=my_df5['total_amount'], x=my_df5.index, palette='mako')
plt.suptitle('Los 5 principales compradores',fontsize='xx-large')
for pos in ['right', 'top', 'bottom', 'left']:
plt.gca().spines[pos].set_visible(False)
ingresos = my_df5['total_amount'].values
for i, ingreso in enumerate(ingresos):
v = '$ ' + str(int(ingreso))
plt.text(s=v, x=i, y=my_df5['total_amount'][i] + 15000, ha='center')
plt.xlabel('')
plt.yticks([])
plt.ylabel(ylabel='')
plt.show()
# RESOLUCIÓN ANALÍTICA
# Previsualizar el DF final
# -------------------------
# "País" "Artículo" "Ventas"
# Pais1 art monto
# Pais2 art monto
# 1) Obtener total x artículo x pais
df_pais_articulo = my_df.groupby(['country_name', 'article_name']).sum()
# 2) Obtener la lista de paises
paises = my_df.groupby('country_name').sum().index.values
# 3) Creo el DF final, pero aún sin datos
my_df6 = pd.DataFrame(columns=['Artículo', 'Ventas'], index=paises)
# 4) Procesar el DF df_pais_articulo y obtener las ventas maximas x artículo y guardarlas en my_df5
for p in paises:
df = df_pais_articulo.loc[p]
v = df.max()['total_amount']
a = df[(df['total_amount'] == v)].index[0]
my_df6.loc[p] = {'Artículo': a, 'Ventas': v}
my_df6 = my_df6.sort_values(['Artículo', 'Ventas'])
my_df6.reset_index(inplace=True, drop=False)
my_df6.columns = ['País','Artículo', 'Ventas']
print(my_df6)
País Artículo Ventas
0 Puerto Rico CPU 1256.58
1 Uruguay Full Pc 8511.24
2 Bolivia Full Pc 10639.05
3 Costa Rica Full Pc 23405.91
4 Guatemala Full Pc 27661.53
5 El Salvador Full Pc 40428.39
6 Venezuela Full Pc 44684.01
7 Peru Full Pc 51067.44
8 Colombia Full Pc 72345.54
9 Argentina Full Pc 95751.45
10 Brazil Full Pc 134052.03
11 Paraguay Monitor 4370.0
12 Honduras Notebook 14000.0
13 Mexico Notebook 44000.0
14 Chile Smartphone 6300.0
15 Ecuador Smartphone 7875.0
# RESOLUCIÓN GRÁFICA
c = sns.color_palette('mako', n_colors=my_df6.nunique(0)[1])
df_pivot = pd.pivot_table(my_df6, index='País', columns='Artículo', values='Ventas', aggfunc='sum')
df_pivot = df_pivot.sort_values(['CPU','Full Pc', 'Monitor', 'Notebook','Smartphone'], ascending=False)
df_pivot.plot.barh(stacked=True, color=c, width=0.9)
plt.suptitle(t='Producto más vendido por país', y=1.2, fontsize='xx-large')
for pos in ['right', 'top', 'bottom', 'left']:
plt.gca().spines[pos].set_visible(False)
ingresos = my_df6.values
for ingreso in ingresos:
v = '$ ' + str(int(ingreso[2]))
i = df_pivot.index.values
plt.text(s=v, x=ingreso[2] + 2000, y=np.where(i==ingreso[0])[0][0], va='center')
plt.xlabel('')
plt.xticks([])
plt.ylabel(ylabel='')
plt.show()
# RESOLUCIÓN ANALÍTICA
# Previsualizar el DF final
# -------------------------------------------------
# índices columnas
# "week" "article_name" "quantity " "total_amount"
# 1 Full Pc unidades monto
# 2 Full Pc unidades monto
# 3 Full Pc unidades monto
# 4 Full Pc unidades monto
# 1) Obtener total x semana x producto
df_semana_articulo = my_df.groupby(['week', 'article_name']).sum()
# 2) Reduzco el DF df_semana_articulo a sólo el artículo Full Pc (el más vendido)
indices = []
for i in range(len(df_semana_articulo)):
if df_semana_articulo.index[i][1] != 'Full Pc':
indices.append(i)
my_df7 = df_semana_articulo.drop(df_semana_articulo.index[indices])
print(my_df7)
quantity total_amount
week article_name
1 Full Pc 97 206397.57
2 Full Pc 76 161713.56
3 Full Pc 49 104262.69
4 Full Pc 31 65962.11
# RESOLUCIÓN GRÁFICA
label = ['Semana '+ str(x) for x in range(1,len(my_df7)+1)]
c = sns.color_palette('mako', n_colors=len(my_df7))
plt.suptitle(t='Variación de ventas de Full PC a lo largo del mes', y=1.2, fontsize='xx-large')
_, _, autotexts = plt.pie(my_df7['total_amount'], labels=label, colors=c,radius=1.7,
autopct='%1.1f%%')
for ins in autotexts:
ins.set_color('white')
plt.show()