# A veces necesitamos instalar nuevas librerías en nuestros proyectos
!pip install openpyxl==3.0.10
# imports
import numpy as np
import pandas as pd
import sqlite3 as sql3
import openpyxl
import matplotlib.pyplot as plt
import seaborn as sns
# Levantar los datos de las diferentes fuentes en dataframes
# Artículos
connection = sql3.connect('/work/data/articles.db')
sql_query = pd.read_sql_query('SELECT * FROM articles', connection)
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 dataframe 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)
# Exploración del dataframe 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)
# Exploración del dataframe 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)
# Cambiar tipo de dato de unit_price de str a float
df_articles['unit_price'] = df_articles['unit_price'].astype(float)
print(df_articles.dtypes)
# Crear copia del dataframe df_orders
my_df = df_orders.copy()
# Cambiar el índice del dataframe artículos
df_articles.set_index('article_id',inplace = True)
# Agregar columnas y usar un campo "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'])
# Reemplazar los valores en el nuevo dataframe
# 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 en un solo paso 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)
print(my_df)
# RESOLUCIÓN ANALÍTICA
# Manipulación de datos y armado del dataframe
df1=my_df.groupby('article_name').sum()
por_cant = df1.sort_values('quantity', ascending=False).head(10)
# Muestra del resultado por pantalla
print(por_cant['quantity'].head(1))
# RESOLUCIÓN GRÁFICA
# Definición de estilos a usar en el gráfico
df1_axis_style = 'darkred'
def show_values(axs, orient="v", space=.01):
def _single(ax):
if orient == "v":
for p in ax.patches:
_x = p.get_x() + p.get_width() / 2
_y = p.get_y() + p.get_height() + (p.get_height()*0.01)
value = '{:.0f}'.format(p.get_height())
ax.text(_x, _y, value, ha="center")
elif orient == "h":
for p in ax.patches:
_x = p.get_x() + p.get_width() + float(space)
_y = p.get_y() + p.get_height() - (p.get_height()*0.5)
value = '{:.0f}'.format(p.get_width())
ax.text(_x, _y, value, ha="left")
if isinstance(axs, np.ndarray):
for idx, ax in np.ndenumerate(axs):
_single(ax)
else:
_single(axs)
# Armado del gráfico
show_values(sns.barplot(y=por_cant["quantity"], x=por_cant.index, palette='rocket', data=por_cant), 'v')
plt.title('Productos más vendidos en Unidades')
plt.legend(['Producto más vendido (']+por_cant.head(1).index+[')'])
plt.ylabel('Cantidad')
plt.xlabel('Artículos')
plt.xticks(rotation=45, color=df1_axis_style)
plt.yticks(np.arange(0, 500, 50), rotation=25, color=df1_axis_style)
plt.show()
# RESOLUCIÓN ANALÍTICA
# Manipulación de datos y armado del dataframe
df2 = (my_df.groupby(by='article_name').sum()).sort_values('total_amount',ascending=False).head(5)
# Muestra del resultado por pantalla
print(df2['total_amount'].head(1))
# RESOLUCIÓN GRÁFICA
# Definición de estilos a usar en el gráfico
df2_axis_style = 'indigo'
# Armado del gráfico
df2['total_amount'].head(5).plot(kind='barh', title= 'Articulos con mayores ingresos en USD', color=['darkviolet', 'mediumorchid', 'thistle', 'plum', 'violet'])
for index, value in enumerate(df2['total_amount']):
plt.text(value, index, str(int(value)))
plt.legend(['Artículo con Mayores Ingresos (']+df2.head(1).index+[')'])
plt.ylabel('Productos')
plt.xlabel('Importe en miles de USD')
plt.xticks(np.arange(0, 750000, 100000), rotation=45, color=df2_axis_style)
plt.yticks(rotation=25, color=df2_axis_style)
plt.show()
# RESOLUCIÓN ANALÍTICA
# Manipulación de datos y armado del dataframe
df3 = (my_df.groupby(by='seller_name').sum()).sort_values('total_amount',ascending=False)
# Muestra del resultado por pantalla
print(df3[['quantity']+['total_amount']].head(3))
# RESOLUCIÓN GRÁFICA
# Definición de estilos a usar en el gráfico
df3_axis_style = 'olive'
colors=[]
counter=0
for amount in df3['total_amount']:
if counter == 0:
colors.append('green')
else:
colors.append('gold')
counter += 1
# Armado del gráfico
plt.bar(df3.index,df3['total_amount'], color=colors)
plt.title('Mejores vendedores del mes')
plt.legend(['Mejor vendedor del mes (']+df3.head(1).index+[')'])
plt.xlabel('Vendedores')
plt.ylabel('Total vendido en miles de USD')
plt.yticks(np.arange(0, 250000, 25000), color=df3_axis_style)
plt.xticks(rotation=60, color=df3_axis_style, ha="right")
plt.show()
# RESOLUCIÓN ANALÍTICA
# Manipulación de datos y armado del dataframe
df4 = (my_df.groupby(by='week').sum()).sort_values('total_amount',ascending=False)
# Muestra del resultado por pantalla
print(df4['total_amount'])
# RESOLUCIÓN GRÁFICA
# Definición de estilos a usar en el gráfico
df4_axis_style = 'crimson'
df4g = (my_df.groupby(by='week').sum()).sort_values('total_amount',ascending=False)
cdf4=['fuchsia', 'orchid', 'hotpink', 'pink']
# Armado del gráfico
plt.bar(df4g.index, df4g['total_amount'], color=cdf4)
for index, value in enumerate(df4['total_amount']):
plt.text(index+0.75, value, str(int(value)))
tendencia = []
for index in df4.index:
if index == 1:
tendencia.append(int(df4['total_amount'].loc[index]*1.05))
tendencia.append(int(df4['total_amount'].loc[index]*0.9))
else:
tendencia.append(int(df4['total_amount'].loc[index]*0.9))
plt.title('Ventas por semana')
plt.xticks(np.arange(1, 5, 1), color=df4_axis_style)
plt.yticks(np.arange(0, 600000, 100000), rotation=40, color=df4_axis_style)
plt.xlabel('Semana')
plt.ylabel('Total vendido en miles de USD')
plt.plot(tendencia, label='Tendencia de ventas', color=df4_axis_style)
plt.legend()
plt.show()
# RESOLUCIÓN ANALÍTICA
# Manipulación de datos y armado del dataframe
df5 = (my_df.groupby(by='country_name').sum()).sort_values('total_amount',ascending=False)
# Muestra del resultado por pantalla
print(df5['total_amount'].head(1))
# RESOLUCIÓN GRÁFICA
# Definición de estilos a usar en el gráfico
total_amount_5 = df5['total_amount'].head(5).sum()
def autopct_format (prct_values):
return '\nUSD {:.0f}'.format(total_amount_5*prct_values/100)
# Armado del gráfico
df5['total_amount'].head(5).plot(kind='pie', shadow=True, explode=(0, 0.2, 0, 0.2, 0.2), autopct=autopct_format)
plt.title('Top 5 de Países que más han comprado')
plt.legend(['País que más ha comprado (']+df5.head(1).index+[')'], bbox_to_anchor=(0.5, -0.1), loc='upper center')
plt.ylabel('', rotation=90)
plt.xlabel('Países')
plt.show()
# RESOLUCIÓN ANALÍTICA
# Manipulación de datos y armado del dataframe
df6 = ((my_df.groupby(by='seller_name').sum()).sort_values('total_amount',ascending=True)).head(5)
# Muestra del resultado por pantalla
print(df6['total_amount'])
# RESOLUCIÓN GRÁFICA
# Definición de estilos a usar en el gráfico
df6_axis_style = 'red'
colors=[]
counter=0
for amount in df6['total_amount']:
if counter > 0:
colors.append('salmon')
else:
colors.append('red')
counter += 1
plt.bar(df6.index,df6['total_amount'], color=colors)
plt.title('Los 5 vendedores con menos ventas del mes')
plt.legend(['El vendedor con peor performance (']+df6.index+[')'])
plt.xlabel('Vendedores')
plt.ylabel('Total vendido en miles de USD')
plt.yticks(np.arange(0, 125000, 25000), color=df6_axis_style)
plt.xticks(rotation=30, color=df6_axis_style, ha="right")
plt.show()
# RESOLUCIÓN ANALÍTICA
# Manipulación de datos y armado del dataframe
df7_pt = pd.DataFrame(pd.pivot_table(my_df.copy(),index=['country_name'], columns=['week'], values=["total_amount"], aggfunc=[np.sum], margins=True)).reset_index()
df7_pt.columns = ['country_name', '1', '2', '3', '4', 'total_amount']
df7_pt.set_index('country_name', inplace=True)
df7_pt.drop(['All'], axis='index', inplace=True)
df7_pt.sort_values(by='total_amount', ascending=False, inplace=True)
# Muestra del resultado por pantalla
df7_pt.head(3).style.format({"1": "USD {:20,.2f}", "2": "USD {:20,.2f}", "3": "USD {:20,.2f}", "4": "USD {:20,.2f}", "total_amount":"USD {:20,.2f}"})\
.format({"country_name": lambda x:x.lower()})\
.bar(subset=["1"], color='#1F77B4')\
.bar(subset=["2"], color='#FF7F0E')\
.bar(subset=["3"], color='#2CA02C')\
.bar(subset=["4"], color='#D62728')\
.bar(subset=["total_amount"], color='#FFA07A')
# RESOLUCIÓN GRÁFICA
# Armado del gráfico
df7g = df7_pt.head(3)
plt.bar(df7g.index, df7g['1'], label='Semana 1')
plt.bar(df7g.index, df7g['2'], label='Semana 2', bottom=df7g['1'])
plt.bar(df7g.index, df7g['3'], label='Semana 3', bottom=df7g['1']+df7g['2'])
plt.bar(df7g.index, df7g['4'], label='Semana 4', bottom=df7g['1']+df7g['2']+df7g['3'])
plt.title('Top 3 de países con más ventas en el mes en monto desglosado por semana')
plt.ylabel('Total Ventas en USD desglosado por semana')
plt.xlabel('Países')
plt.yticks(rotation=45)
plt.xticks(rotation=45, ha="right")
plt.legend()
plt.show()