# A veces necesitamos instalar nuevas librerías en nuestros proyectos
!pip install openpyxl==3.0.10
Requirement already satisfied: openpyxl==3.0.10 in /root/venv/lib/python3.9/site-packages (3.0.10)
Requirement already satisfied: et-xmlfile in /root/venv/lib/python3.9/site-packages (from openpyxl==3.0.10) (1.1.0)
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 matplotlib.pyplot as plt
import seaborn as sns
#import openpyxl # para levantar excel de otros paqueres (no office)
# Levanto los datos en 3 diferentes dataframes
#Articulos
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'])
#df_articles
#Vendedores
df_sellers = pd.read_excel('/work/data/sellers.xlsx', index_col=0)
#df_sellers
#Ordenes
df_orders = pd.read_csv('/work/data/orders.csv')
df_orders
#sql_query
#df_articles
#df_sellers
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
# Exploración del df de artículos
print('Muestra de datos')
print(df_articles.head())
print('\nForma del dataframe')
print(df_articles.shape)
print('\nBuscar valores nulos')
print(df_articles.isnull().sum())
print('\nFormato de los datos del dataframe')
print(df_articles.dtypes)
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
Forma del dataframe
(31, 3)
Buscar valores nulos
article_id 0
article_name 0
unit_price 0
dtype: int64
Formato de los datos del dataframe
article_id int64
article_name object
unit_price object
dtype: object
# Exploración del df de vendedores
print('Muestra de datos')
print(df_sellers.head())
print('\nForma del dataframe')
print(df_sellers.shape)
print('\nBuscar valores nulos')
print(df_sellers.isnull().sum())
print('\nFormato de los datos del dataframe')
print(df_sellers.dtypes)
Muestra de datos
seller_name
seller_id
1 Aveline Swanwick
2 Jase Doy
3 Oliviero Charkham
4 Cornie Wynrehame
5 Ewell Peres
Forma del dataframe
(15, 1)
Buscar valores nulos
seller_name 0
dtype: int64
Formato de los datos del dataframe
seller_name object
dtype: object
# Exploración del df de órdenes
print('Muestra de datos')
print(df_orders.head())
print('\nForma del dataframe')
print(df_orders.shape)
print('\nBuscar valores nulos')
print(df_orders.isnull().sum())
print('\nFormato de los datos del dataframe')
print(df_orders.dtypes)
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
Forma del dataframe
(1000, 6)
Buscar valores nulos
order_id 0
week 0
article_id 0
quantity 0
seller_id 0
country_name 0
dtype: int64
Formato de los datos del dataframe
order_id int64
week int64
article_id int64
quantity int64
seller_id int64
country_name object
dtype: object
# Cambiar a float los precios unitarios
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 indice del df_articles común de 1, 2 3 por articles_id
df_articles.set_index('article_id', inplace=True)
# Agrego 3 columnas y pongo el campo que me va a servir de "ancla" para buscar la información real.
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'])
print(df_articles)
#print(my_df.head())
article_name unit_price
article_id
20015 Smartphone 525.00
20016 Full Pc 2127.81
20017 Monitor 230.00
20018 Tablet 130.00
20019 Desk 130.10
20020 Chair 335.64
20021 Modem 67.50
20022 Range Extender 20.45
20023 Notebook 1000.00
20024 Netbook 145.00
20025 HDD 54.62
20026 SDD 22.00
20027 Ram Memory 35.95
20028 Motherboard 138.38
20029 Mouse 30.30
20030 Fan Cooler 4.25
20031 Webcam 20.07
20032 Keyboard 22.60
20033 Headphones 23.30
20034 Scanner 185.00
20035 Case 37.90
20036 Video Card 131.50
20037 CPU 139.62
20038 Power Supply 43.95
20039 Water Cooling 67.50
20040 Heatsink 10.00
20041 Usb Cable 2.95
20042 Sata Cable 2.14
20043 Pci Express Port 10.12
20044 Wi-Fi Card 59.61
20045 Mesh Wi-Fi X 2 32.50
#Reemplazar los valores reales en el df
for i in range (len(my_df.index)): #len(my_df.index) devuelva la cantidad de filas (registros)
#reemplazo el nombre del articulo usando el id guardado en my_df
article = df_articles.loc[my_df.loc[i]['article_id']]['article_name']
my_df.loc[i, 'article_name'] = article
#reemplazo el nombre del vendedor usando el id guardado en my_df
my_df.loc[i, 'seller_name'] = df_sellers.loc[my_df.loc[i]['seller_id']]['seller_name']
#busco el precio unitario y lo multiplico por la cantidad de unidades vendidas.
my_df.loc[i, 'total_amount'] = df_articles.loc[my_df.loc[i]['article_id']]['unit_price'] * my_df.loc[i, 'quantity']
#elimino las columnas que no utilizo
my_df.drop(['article_id', 'seller_id', 'order_id'], axis='columns', inplace=True)
print(my_df.head())
week quantity country_name article_name total_amount seller_name
0 1 10 Peru Water Cooling 675.0 Cirilo Grandham
1 1 15 Peru Mouse 454.5 Ewell Peres
2 1 5 Bolivia Netbook 725.0 Janel O'Curran
3 1 9 Brazil Tablet 1170.0 Janel O'Curran
4 1 6 Mexico Case 227.4 Daisie Slograve
# RESOLUCIÓN ANALÍTICA
#1. Sumo todos los artículos por el mismo nombre y tomo la cantidad
#2. Le digo que me los agrupe según (groupby) 'article_name'
#3. Le digo que me ordene los valores por 'quantity', y que el ascending sea False (mayor a menor)
#4. Imprimo solo el primer resultado con 'head(1)'
my_df2 = my_df.groupby('article_name').sum()
mas_cantidad = my_df2.sort_values('quantity', ascending=False)
print(mas_cantidad['quantity'].head(1))
article_name
HDD 413
Name: quantity, dtype: int64
# RESOLUCIÓN GRÁFICA
#Análisis de la resolución analítica: El artículo más vendido es 'HDD 413'
#Hice un gráfico de barras con la cantidad de los artículos más vendidos
sns.set_theme(style = 'whitegrid')
sns.barplot(x=my_df2.index, y=my_df2['quantity'], data = my_df2,
order=my_df2.sort_values('quantity', ascending=False).index,
palette='cool').set(title='Ventas por articulo')
plt.ylabel("Cantidad")
plt.xlabel(" ")
plt.xticks(rotation=90)
plt.show()
# RESOLUCIÓN ANALÍTICA
#1. Sumé todos los artículos por el mismo nombre y tomé 'total_amount'
#2. Los agrupé según (groupby) 'article_name'
#3. Ordené los valores por 'total_amount', con ascending en False (mayor a menor).
#4. Imprimí los primeros 5 resultados con 'head()'
my_df2 = my_df.groupby('article_name').sum()
mas_ingresos = my_df2.sort_values('total_amount', ascending=False).head()
print('Artículos con más ingresos', mas_ingresos['total_amount'])
Artículos con más ingresos 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
#Análisis de la resolución analítica: El artículo que más ingresos generó fue 'Full Pc'
#Hice gráfico de torta que muestra los porcentajes de venta de estos 5 artículos.
#Destaqué el más vendido separándolo para ver mejor qué porción representa.
colors = sns.color_palette('cool')
e = (0.1, 0, 0, 0, 0)
plt.pie(x=mas_ingresos['total_amount'], labels=mas_ingresos.index, colors=colors,
explode=e, startangle=270, autopct='%.0f%%', rotatelabels='true')
plt.title('Top 5 de los artículos que más ingresos generaron')
plt.show()
#OTRO ANÁLISIS
#Noté que el gráfico anterior no es completamente acertado ya que estaría faltando una categoría
#'Otros' que muestre el total de las ventas para que se pueda dimensionar mejor qué porcentaje
#represnta realmente el artículo más vendido.
#Para esto, ordené los artículos por ventas totales de forma inversa, y dejé afuera los últimos
#5 elementos, que corresponderías con los 5 más vendidos.
#A todo ese resto lo sumé.
my_df2 = my_df.groupby('article_name').sum()
mas_ingresos = my_df2.sort_values('total_amount', ascending=False).head()
otros = my_df2.sort_values('total_amount', ascending=True).head(-5)
total_otros = sum(otros['total_amount'])
print('Artículos con más ingresos', mas_ingresos['total_amount'])
print('Resto', total_otros)
Artículos con más ingresos article_name
Full Pc 538335.93
Notebook 251000.00
Smartphone 152250.00
Chair 69477.48
Tablet 48620.00
Name: total_amount, dtype: float64
Resto 416124.42999999993
#RESOLUCIÓN GRÁFICA
#Intenté agregar este resto como nuevo dato a la lista anterior para poder hacer el gráfico de
#torta, pero no pude por incompatibilidad de dimensiones, entre otros errores.
#Como tenía todos los datos, decidí forzarlo dándole yo misma los nombres y valores.
colors = sns.color_palette('cool')
e = (0.1, 0, 0, 0, 0, 0)
valores = [538335.93, 416124.42, 251000.00, 152250.00, 69477.48, 48620.00]
nombres = ['Full Pc', 'Otros', 'Notebook', 'Smartphone', 'Chair', 'Tablet']
plt.pie(valores, labels=nombres, colors=colors, explode=e, startangle=320, autopct='%.0f%%',
rotatelabels='true')
plt.title('Artículos que más ingresos generaron')
plt.show()
# RESOLUCIÓN ANALÍTICA
#Agrupé todos los vendedores por el mismo nombre y tomé el 'total_amount'
#Agrupé según (groupby) 'seller_name'
#Ordené los valores por 'total_amount', con ascending en False (= descendiente)
#Imprimo solo el primer resultado con 'head(1)'
my_df2 = my_df.groupby('seller_name').sum().sort_values('total_amount', ascending = False)
mejor_vendedor = my_df2.sort_values('total_amount', ascending=False)
print(mejor_vendedor['total_amount'].head(1))
seller_name
Janel O'Curran 192832.47
Name: total_amount, dtype: float64
# RESOLUCIÓN GRÁFICA
# Análisis de la resolución analítica: El mejor vendedor del mes fue Janel O'Curran
# Hice un gráfico de barras, y acomodé el nombre de los vendedores en otro ángulo.
sns.barplot(x=my_df2.index, y=my_df2['total_amount'], data = my_df2, order=my_df2.sort_values('total_amount', ascending=False).index, palette='cool').set(title='Empleado del Mes')
plt.ylabel("Monto")
plt.xticks(rotation=75)
plt.show()
# RESOLUCIÓN ANALÍTICA
#Agrupé por semana y tomé el 'total_amount'
#Agrupé según (groupby) 'week'
#Ordené los valores por 'total_amount', con ascending en False (= descendiente)
#Imprimí todos los resultados que eran 4 con head()'.
my_df2 = my_df.groupby('week').sum()
por_semanas = my_df2.sort_values('total_amount', ascending=False)
print(por_semanas['total_amount'].head())
week
1 507458.81
2 415364.44
3 329140.03
4 223844.56
Name: total_amount, dtype: float64
# RESOLUCIÓN GRÁFICA
#Análisis de la resolución analítica: Las ventas han ido disminuyendo.
#Hice un gráfico de línea con sombra que me muestra el descenso en las ventas.
sns.lineplot(x=my_df2.index, y=my_df2['total_amount'], data = my_df2, marker = "o",
palette = 'cool').set(title='Ventas del Mes')
plt.xlabel("Semana")
plt.ylabel("Monto")
plt.fill_between(my_df2.index, my_df2['total_amount'], color = 'turquoise', alpha = 0.5)
plt.show()
# RESOLUCIÓN ANALÍTICA
#Agrupé todos los países por el mismo nombre y tomé su 'total_amount'.
#Los agrupé según (groupby) 'country_name'.
#Ordené los valores por 'total_amount', tomando el ascending como False (= descendiente)
#Imprimí solo el primer resultado con 'head(1)'
my_df2 = my_df.groupby('country_name').sum()
por_total = my_df2.sort_values('total_amount', ascending=False)
print(por_total['total_amount'].head(1))
country_name
Brazil 441271.85
Name: total_amount, dtype: float64
#RESOLUCIÓN GRÁFICA
#Análisis de la resolución analítica: El país que más ingresos generó fue Brazil.
#Lo representé con un gráfico de barras por país y total de ventas.
#Para una mejor lectura, cambié el ángulo del nombre de los países.
#Eliminé el título del eje correspondiente a los países para evitar redundancias.
sns.barplot(y=my_df2.index, x=my_df2['total_amount'], data = my_df2,
order=my_df2.sort_values('total_amount', ascending=False).index,
palette='cool').set(title='País que más nos compró')
plt.xlabel("Monto")
plt.ylabel(" ")
plt.show()
# RESOLUCIÓN ANALÍTICA
#Agrupé todos los países por el mismo nombre y tomé la cantidad, 'quantity'.
#Los agrupé según (groupby) 'country_name'.
#Ordené los valores por 'quantity', con el ascending en False (= descendiente)
#Imprimí los primeros 3 resultados con 'head(3)'
my_df2 = my_df.groupby('country_name').sum()
por_cantidad = my_df2.sort_values('quantity', ascending=False)
print(por_cantidad['quantity'].head(3))
country_name
Brazil 2515
Peru 1027
Argentina 947
Name: quantity, dtype: int64
#RESOLUCIÓN GRÁFICA
#Análisis de la resolución: Además de ser el país que generó más ingresos, Brazil fue el
#que compró más cantidad de productos.
#Hice un gráfico de barras indicando la cantidad de artículos comprados.
#Limité la cantidad de países mostrados a 5.
sns.barplot(x=my_df2.index, y=my_df2['quantity'], data = my_df2,
order= my_df2[1:6].index,
palette='cool').set(title='País que más productos compró')
plt.ylabel("Cantidad de Productos")
plt.xlabel(" ")
plt.xticks(rotation=90)
plt.show()
# RESOLUCIÓN ANALÍTICA
#1. Sumé todos los artículos por el mismo nombre y tomé el 'total_amount'.
#2. Los agrupé según (groupby) 'article_name'.
#3. Ordeneé los valores por 'total_amount'.
#4. Imprimí solo los 10 primeros resultados con 'head(10)'.
my_df2 = my_df.groupby('article_name').sum()
por_total = my_df2.sort_values('total_amount', ascending=True)
print(por_total['total_amount'].head(10))
article_name
Sata Cable 564.96
Usb Cable 805.35
Fan Cooler 871.25
Heatsink 2800.00
Pci Express Port 2944.92
Keyboard 3729.00
Webcam 4596.03
Headphones 5568.70
Range Extender 5746.45
Mesh Wi-Fi X 2 6922.50
Name: total_amount, dtype: float64
#RESOLUCIÓN GRÁFICA
#Análisis de la resolución: Ordenando los artículos de manera inversa puedo acceder a cuáles
#han sido menos vendidos y proceder a aplicar alguna estrategia de venta para generarles más salida.
sns.barplot(x=my_df2.index, y=my_df2['total_amount'], data = my_df2, order=my_df2.sort_values('total_amount', ascending=False).index, palette='cool').set(title='Productos que necesitan una mejor estrategia de venta')
plt.ylabel("Monto que se vendió")
plt.xticks(rotation=90)
plt.show()
#Las conclusiones y propuestas las fui agregando como comentario en cada uno de los casos
#para mayor claridad.