# Librería a instalar para el proyecto
!pip install openpyxl==3.0.10
# Librería importadas
import openpyxl
import pandas as pd
import seaborn as sns
import sqlite3 as sq3
import matplotlib.pyplot as plt
# Settings
# Seaborn theme
sns.set_theme(style="whitegrid")
# Matplotlib params
params = {'legend.fontsize': 'large',
'figure.figsize': (16, 10),
'axes.labelsize': 'x-large',
'axes.titlesize':'x-large',
'xtick.labelsize':'large',
'ytick.labelsize':'large'}
plt.rcParams.update(params)
# 3 archivos
articles_db = "data/articles.db"
sellers_file = "data/sellers.xlsx"
orders_file = "data/orders.csv"
# Artículos
conection = sq3.connect(articles_db)
# Pandas función para obtener dataframe de una BD
df_articles = pd.read_sql_query('SELECT * FROM articles', conection)
# Vendedores
df_sellers = pd.read_excel(sellers_file)
# Órdenes
df_orders = pd.read_csv(orders_file)
# Chequear valores únicos para article_id
print(f'¿Son únicos los índices para article_id? {df_articles["article_id"].is_unique}')
# df_sellers info
print('Información de vendedores')
df_sellers.info()
# Chequear valores únicos para seller_id
print(f"¿Son únicos los índices para seller_id? {df_sellers['seller_id'].is_unique}")
# df_orders info
print('Información de órdenes')
df_orders.info()
# Chequear valores únicos para order_id
print(f"¿Son únicos los índices para order_id? {df_orders['order_id'].is_unique}")
# Convertir unit_price a float
df_articles = df_articles.astype({"unit_price": float})
print(f'El tipo de dato de unit_price fue cambiado a {df_articles["unit_price"].dtypes}.')
# Df merge
my_df = df_orders.merge(df_articles, how='left', on='article_id')
my_df = my_df.merge(df_sellers, how='left', on='seller_id')
# Nueva columna total_amount
my_df['total_amount'] = my_df.quantity * my_df.unit_price
# Elimar cols ids' y unit_price cols
my_df.drop(['order_id', 'article_id', 'seller_id', 'unit_price'], axis=1, inplace=True) #axis=1 refers to columns
# Ordenar columnas
cols_order = ['article_name', 'quantity', 'total_amount', 'seller_name', 'country_name', 'week']
my_df = my_df[cols_order]
my_df.round(2) # dos decimales
# RESOLUCIÓN ANALÍTICA
most_sold_article = my_df.groupby(['article_name'])['quantity'].sum().reset_index()
most_sold_article = most_sold_article.sort_values(by = 'quantity', ascending=False).reset_index(drop=True)
most_sold_article
# Artículo más vendido
print(f'El artículo más vendido es el {most_sold_article["article_name"][0]} con un total de {most_sold_article["quantity"][0]} unidades.')
# RESOLUCIÓN GRÁFICA
plt.figure(figsize=(16,10))
color_max = ['grey' if (x < max(most_sold_article['quantity'])) else '#ff725e' for x in most_sold_article['quantity']] # Color for max
sns.barplot(y='article_name', x='quantity', data=most_sold_article, palette= color_max, orient = 'h')
plt.ylabel("Artículo")
plt.xlabel("Cantidad (unidades)")
plt.show()
# RESOLUCIÓN ANALÍTICA
most_amount_article = my_df.groupby(['article_name'])['total_amount'].sum().reset_index()
most_amount_article = most_amount_article.sort_values(by = 'total_amount', ascending=False).reset_index(drop=True)
most_amount_article.round(2)
# Artículo mayor montó generó
print(f'El artículo que mayor monto total generó es {most_amount_article["article_name"][0]} con un total de USD {most_amount_article["total_amount"][0]:0.2f}.')
# RESOLUCIÓN GRÁFICA
plt.figure(figsize=(16,10))
color_max = ['grey' if (x < max(most_amount_article['total_amount'])) else '#ff725e' for x in most_amount_article['total_amount']]
sns.barplot(y='article_name', x='total_amount', data=most_amount_article, palette= color_max, orient = 'h')
plt.ylabel("Artículo")
plt.xlabel("Monto total (USD)")
plt.show()
# RESOLUCIÓN ANALÍTICA
best_seller = my_df.groupby(['seller_name'])['total_amount'].sum().reset_index()
best_seller = best_seller.sort_values(by = 'total_amount', ascending=False).reset_index(drop=True)
best_seller.round(2)
# Mejor vendedor del mes
print(f'El mejor vendedor del mes es {best_seller["seller_name"][0]} con un total de USD {best_seller["total_amount"][0]:0.2f} vendidos.')
# RESOLUCIÓN GRÁFICA
plt.figure(figsize=(14,10))
color_max = ['grey' if (x < max(best_seller['total_amount'])) else '#ff725e' for x in best_seller['total_amount']]
sns.barplot(y='seller_name', x='total_amount', data=best_seller, palette= color_max, orient = 'h')
plt.ylabel("Vendedor")
plt.xlabel("Monto total (USD)")
plt.show()
# RESOLUCIÓN ANALÍTICA
best_week = my_df.groupby(['week'])['total_amount'].sum().reset_index()
# Defino total_amount por quincenas para utilizar luego
amount_quincena1 = best_week["total_amount"][0] + best_week["total_amount"][1]
amount_quincena2 = best_week["total_amount"][2] + best_week["total_amount"][3]
# Ordeno las semanas por total_amount
best_week = best_week.sort_values(by = 'total_amount', ascending=False).reset_index(drop=True)
best_week.round(2)
# Promedio de la diferencia monto total entre semanas
dif12 = best_week["total_amount"][0] - best_week["total_amount"][1]
dif23 = best_week["total_amount"][1] - best_week["total_amount"][2]
dif34 = best_week["total_amount"][2] - best_week["total_amount"][3]
mean_dif = (dif12 + dif23 + dif34)/3
mean_dif.round(2)
print(f"El promedio de la diferencia monto total entre semanas es USD {mean_dif:0.2f}")
# ¿Hay variaciones a lo largo del mes?
# ¿Esa diferencia promedio es cero o distinta de cero?
if mean_dif == 0:
print(f'No hay variaciones de ventas a lo largo del mes.')
else:
print(f'Hay variaciones de ventas a lo largo del mes.')
print(f'La diferencia de monto total entre semanas fue USD {mean_dif:0.2f} en promedio.')
# Mejor semana: best_week["week"][0] datos ordenados en forma descendente
print(f'La semana {best_week["week"][0]} es la mejor del mes con un total de USD {best_week["total_amount"][0]:0.2f} vendidos.')
# Peor semana: best_week["week"][3] datos ordenados en forma descendente
print(f'Por otro lado, la semana {best_week["week"][3]} es la peor del mes con un total de USD {best_week["total_amount"][3]:0.2f} vendidos.')
# Campaña de promociones
print("Se sugiere lanzar una campaña de promociones en la quincena que menor monto de ventas obtuvo.")
if amount_quincena1 < amount_quincena2:
print(f'En base a los resultados, se debería lanzar en la primera quincena del mes.')
else:
print(f'En base a los resultados, se debería lanzar en la segunda quincena del mes.')
# RESOLUCIÓN GRÁFICA
plt.figure(figsize=(16,10))
sns.lineplot(x='week', y='total_amount', data=best_week, color= '#ff725e', marker="o")
plt.xticks([1, 2, 3, 4])
plt.xlabel("Semana")
plt.ylabel("Monto total (USD)")
# Informo la diferencia promedio
plt.text(3, 480000, "Promedio de la diferencia monto total entre semanas (USD):", horizontalalignment='center', size='x-large', color='black')
plt.text(3, 460000, mean_dif.round(2), horizontalalignment='center', size='xx-large', color='black')
plt.show()
# RESOLUCIÓN ANALÍTICA
# Monto total por país
amounts_country = my_df.groupby(['country_name'])['total_amount'].sum().reset_index()
amounts_country = amounts_country.sort_values(by = 'total_amount', ascending=False).reset_index(drop=True)
# Media monto total por país
mean_amounts_country = amounts_country["total_amount"].mean()
print(f'La media del monto total por país es USD {mean_amounts_country:0.2f}')
# Nueva columna con tot_amount - mean_amounts_country
amounts_country['mean_diff'] = amounts_country.total_amount - mean_amounts_country
amounts_country.round(2)
# Mejores países
best_countries = []
for i in range(0, len(amounts_country)):
if amounts_country['mean_diff'][i] > 0:
best_countries.append(amounts_country['country_name'][i])
else:
pass
print(", ".join(best_countries), 'son los países cuyos montos totales de ventas sobrepasan la media.')
print('Estos representan los mejores países respecto al monto total de ventas.')
print('Para aquellos países por debajo de la media')
print('se deberían aplicar diferentes estrategias de marketing para aumentar sus montos.')
# RESOLUCIÓN GRÁFICA
plt.figure(figsize=(16,8))
two_colors = ['grey' if (x < 0) else '#ff725e' for x in amounts_country['mean_diff']]
sns.barplot(x='country_name', y='mean_diff', data=amounts_country, palette = two_colors)
# Informo la media monto total en gráfico
plt.text(12, 340000, "Media monto total países (USD)", horizontalalignment='center', size='x-large', color='black')
plt.text(12, 310000, mean_amounts_country.round(2), horizontalalignment='center', size='xx-large', color='black')
plt.xlabel("País")
plt.ylabel("Diferencia monto total y media (USD)")
plt.xticks(rotation=90)
plt.show()
# Del dataframe articles_country retener solo aquellos que corresponden a los 5 artículos más vendidos
five_articles_country = articles_country[articles_country['article_name'].isin(list_top_five_articles)]
five_articles_country = five_articles_country.reset_index(drop=True)
cols_ord = ['article_name', 'country_name', 'quantity']
five_articles_country = five_articles_country[cols_ord]
five_articles_country
# RESOLUCIÓN GRÁFICA
plt.figure(figsize=(16,10))
five_articles_country = five_articles_country.sort_values(by = 'quantity', ascending=False).reset_index(drop=True) # Orden por cant
sns.scatterplot(y="country_name", x="quantity", data=five_articles_country, hue="article_name", s=200, palette = "Set2")
plt.ylabel("País")
plt.xlabel("Cantidad (unidades)")
plt.legend(title='Mejores cinco artículos', loc='lower right')
plt.show()
# Cinco artículos más vendidos
print(", ".join(list_top_five_articles), 'son los cinco artículos más vendidos en cantidad.')
print("En el gráfico se pueden observar las unidades vendidas en cada país.")
# Mejor país
best_country = amounts_country['country_name'][0]
print(f'El mejor país respecto al monto total de venta es {best_country}.')
# RESOLUCIÓN ANALÍTICA
# Montos totales de artículos por país
amount_articles_country = my_df.groupby(['country_name', 'article_name'])['total_amount'].sum().reset_index()
amount_articles_country = amount_articles_country.sort_values(by = 'total_amount', ascending=False).reset_index(drop=True)
# Del dataframe amount_articles_country retener solo best_country
amount_articles_bestcountry = amount_articles_country[amount_articles_country['country_name']==best_country]
# Del dataframe amount_articles_bestcountry retener solo aquellos que corresponden a los 5 artículos más vendidos
amount_articles_bestcountry = amount_articles_bestcountry[amount_articles_bestcountry['article_name'].isin(list_top_five_articles)]
amount_articles_bestcountry = amount_articles_bestcountry.sort_values(by = 'total_amount', ascending=False).reset_index(drop=True)
amount_articles_bestcountry.round(2)
print(f'En {best_country}, el artículo {amount_articles_bestcountry["article_name"][0]} representó un monto total de USD {amount_articles_bestcountry["total_amount"][0]} vendidos.')
print(f'Este fue seguido por los artículos {amount_articles_bestcountry["article_name"][1]}, {amount_articles_bestcountry["article_name"][2]} y {amount_articles_bestcountry["article_name"][3]}.')
print(f'El último lugar fue para el artículo {amount_articles_bestcountry["article_name"][4]} que representó un monto total de USD {amount_articles_bestcountry["total_amount"][4]:0.2f} vendidos.')
# RESOLUCIÓN GRÁFICA
plt.figure(figsize=(16,10))
sns.barplot(y='article_name', x='total_amount', data=amount_articles_bestcountry, color= '#ff725e', orient = 'h')
plt.ylabel("Artículo")
plt.xlabel("Monto total (USD)")
# Informo mejor país en gráfico
plt.text(18750, 4, "Mejor país:", horizontalalignment='center', size='x-large', color='black')
plt.text(18750, 4.3, best_country, horizontalalignment='center', size='xx-large', color='black')
plt.show()