Análisis de los 25 retailers más grandes de Estados Unidos
# Importar librerías aquí
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Importar datos aquí
df = pd.read_csv('/work/largest_us_retailers.csv')
df.head()
# Método de pandas para describir las columnas del DataFrame.
df.info()
# Método de pandas para obtener valores de importantes de \\
# tendencia central, de dispersión y los quartiles.
df.describe()
df_sorted = df.sort_values('Sales', ascending=False)
df_sorted
x = df_sorted['Company'][:5] # Aplicamos slicing como en una lista de Python.
y = df_sorted['Sales'][:5]
plt.bar(x, y, color='red')
plt.title('Top 5 retailers')
plt.xlabel('Company')
plt.ylabel('Sales')
plt.xticks(rotation=35) # Método que se usa para rotar el texto de los puntos en X para que no se amontonen.
plt.grid(False)
plt.show()
I. Preguntas del negocio
# Removemos solamente a Walmart US mediante slicing y calculamos el promedio de todas las ventas \\
# con el método ".mean()".
sales_avg = int(df_sorted['Sales'][1:].mean())
print("El promedio de ventas es de ${:,} millones de dolares.".format(sales_avg))
# Hacemos un histograma para ver si existe algún otro sesgo además de Walmart US
sns.histplot(data=df[1:],x='Sales', bins=10, color='red')
plt.xlabel('Ventas')
plt.ylabel('Frecuencia')
plt.title('Ventas en millones de dólares')
plt.grid(False)
plt.show()
# En este caso, considero que no existe ningún otro sesgo más que Walmart US.
# Primero, quitaremos a Walmart US del DataFrame, ya que es nuestro único sesgo.
df_without_walmart = df[1:]
df_without_walmart.head()
# Ahora, para contestar esta pregunta, tomaremos una muestra aleatoria de \\
# la mayoría de los datos y haremos el cálculo.
data_quantity = 0.80 # La muestra será del 80% pero se puede modificar.
df_sample = df_without_walmart.sample(frac=data_quantity)
# Calculamos el promedio de la ventas con el método ".mean()" y lo imprimimos en pantalla.
sales_avg = int(df_sample['Sales'].mean())
print("Las ganancias promedio que generaron el {}% de las empresas (sin contar a Walmart US) ${:,} millones de dólares.".format(int(data_quantity*100), sales_avg))
# Sumamos todas las ventas con el método ".sum()" y lo imprimimos en pantalla.
sales_sum = int(df_sample['Sales'].sum())
print("Las ganancias totales que generaron el {}% de las empresas (sin contar a Walmart US) ${:,} millones de dólares.".format(int(data_quantity*100), sales_sum))
# Graficamos un histograma para ver si existe algún sesgo
sns.histplot(data=df, x='Stores', bins=20, color='red')
plt.title('Quantity of stores (With BIAS)')
plt.show()
# Como vemos, existen 7 outliers, debemos localizarlos y quitarlos del DataFrame.
df_sorted_stores = df.sort_values('Stores', ascending=False)
df_sorted_stores.head(8)
# Verificamos si hemos quitado los bias satisfactoriamente
df_stores_without_outliers = df_sorted_stores[7:]
df_stores_without_outliers.head()
# Volvamos a graficar un histograma para asegurarnos \\
# de que no exite algún otro outlier.
sns.histplot(data=df_stores_without_outliers, x='Stores', bins=20, color='red')
plt.title('Quantity of stores (Without BIAS)')
plt.show()
# Considero que ya no hay outliers.
# Calculamos el promedio de las tiendas con el método ".mean()" y lo imprimimos en pantalla
stores_avg = int(df_stores_without_outliers['Stores'].mean())
print("La mayoría de las empresas tiene, en promedio, {:,} tiendas.".format(stores_avg))
# Sumamos todas las tiendas con el método ".sum()" y lo imprimimos en pantalla.
stores_sum = int(df_stores_without_outliers['Stores'].sum())
print("La mayoría de las empresas tiene, en total, {:,} tiendas.".format(stores_sum))
# ¿Entre más tiendas, mayores las ganancias?
# Con seaborn, podemos visualizar la relación entre tiendas y ganancias.
sns.jointplot(data=df, x='Stores', y='Sales')
# Excluyamos a Walmart US y hagamos una regresión lineal \\
# con el método de seaborn ".limplot()".
df_sorted_sales = df.sort_values('Sales', ascending=False)[1:]
sns.lmplot(data=df_sorted_sales, x='Stores', y='Sales')
# Como podemos observar, la pendiente es prácticamente horizontal, por lo tanto, no existe correlación
# Usaremos el método de pandas ".quantile()" \\
# para obtener los valores máximos y mínimos.
sales_min_value = int(df['Sales'].quantile(q=0-0))
sales_max_value = int(df['Sales'].quantile(q=1.0))
print("Valores con Walmart US: \t min: {:,} \t max: {:,}".format(sales_min_value, sales_max_value))
# Para obtener el rango se resta el valor máximo - valor mínimo.
sales_range = sales_max_value - sales_min_value
print("El rango de ventas es de ${:,} (Contando a Walmart US)".format(sales_range))
# ¿Cuál es el rango de ventas sin Walmart US?
# usando ne nuevo el método ".quantile()" y slicing.
sales_min_value = int(df['Sales'].quantile(q=0-0))
sales_max_value = int(df['Sales'][1:].quantile(q=1.0))
print("Valores sin Walmart US: \t min: {:,} \t max: {:,}".format(sales_min_value, sales_max_value))
# Rango sin Walmart US.
sales_range = sales_max_value - sales_min_value
print("El rango de ventas es de ${:,} (Sin contar a Walmart US)".format(sales_range))
# Obtener las 5 empresas que tienen más tiendas físicas.
df_sorted_stores = df.sort_values('Stores', ascending=False)[:5]
# Guardaremos el resultado en dos listas diferentes, una con el nombre\\
# de la compañía y otra con su respectiva cantidad.
top_stores_companies = list(df_sorted_stores['Company'])
top_stores_cuantities = list(df_sorted_stores['Stores'])
# Ciclo for para imprimir el nombre de la tienda \\
# con su respectiva cantidad de tiendas.
print('Top 5 Compañías con más tiendas físicas:')
for i, company in enumerate(top_stores_companies):
print("\t{}. {}: {:,}".format(i+1, company, int(top_stores_cuantities[i])))
# Gráfico de las 5 empresas que tienen más tiendas físicas.
plt.style.use('ggplot')
#sns.barplot(data=top_companies_with_stores, x='Company', y='Stores')
plt.bar(top_stores_companies, top_stores_cuantities)
plt.ylabel('Stores quantity')
plt.xlabel('Company')
plt.xticks(rotation=40)
plt.show()
# ¿Cuáles son las 5 empresas que más ventas tuvieron?
df_sorted_sales = df.sort_values('Sales', ascending=False)[:5]
# Separaremos el resultado en dos listas, una con el nombre de la compañía \\
# y la otra con su respectiva cantidad de ventas.
top_sales_companies = list(df_sorted_sales['Company'])
top_sales_quantities = list(df_sorted_sales['Sales'])
# Ciclo for para imprimir el nombre de la compañía con su \\
# respectiva cantidad de ventas.
print("Top 5 compañías con más ventas (Millones de Dólares):")
for i, company in enumerate(top_sales_companies):
print("\t{}. {}: ${:,}".format(i+1, company, int(top_sales_quantities[i])))
# Gráfico del Top 5 empresas con más ventas.
plt.style.use('ggplot')
plt.bar(top_sales_companies, top_sales_quantities)
plt.ylabel('Sales')
plt.xlabel('Company')
plt.xticks(rotation=40)
plt.grid(False)
plt.show()
# Hagamos un pequeño script para hacer la comparación de las empresas con \\
# más tiendas físicas y las comapañías con más ventas.
print("¿Alguna de las empresas con más tiendas físicas, está en el Top 5 compañías con más ventas?")
for i, company in enumerate(top_stores_companies):
print(f"\t{i+1}. {company}:", company in top_sales_companies)
# Agrupamos el DataFrame por categoría y hacemos una sumatoria de todos sus atributos.
categories_grouped = df.groupby('Category').sum()
# Nos quedamos solamente con la columna de 'Sales', ordenamos de mayor a menor y lo convertimos \\
# en un diccionario para poder manipularlo.
categories_grouped_sales = dict(categories_grouped.sort_values('Sales', ascending=False)['Sales'])
# Hacemos un ciclo for para que imprima la categoría con su respectiva cantidad de ventas.
print("Categorías con más ventas en Millones de dólares:")
for i, (key, value) in enumerate(categories_grouped_sales.items()):
print("\t{}. {}: ${:,}".format(i+1, key, value))
# Separamos nuestro diccionario en sus llaves y valores para poder usarlo \\
# en una gráfica de barras.
category = categories_grouped_sales.keys()
sales = categories_grouped_sales.values()
plt.bar(category, sales)
plt.title('Ventas por categoría de tienda')
plt.xlabel('Categoría')
plt.ylabel('Ventas ($M de USD)')
plt.xticks(rotation=90)
plt.grid(False)
plt.show()
# Empecemos ordenando de mayor a menor las compañías con más tiendas.
df_sorted_stores = df.sort_values('Stores', ascending=False)
df_sorted_stores.head()
# Guardaremos en listas separadas el nombre, sus ventas y la cantidad de tiendas.
companies = list(df_sorted_stores['Company'])
sales = list(df_sorted_stores['Sales'])
stores = list(df_sorted_stores['Stores'])
# List comprehensions para obtener la relación de \\
# "ventas por cada tienda" y guardaremos los resultados en una lista.
sales_stores_relation = [sales[i]/stores[i] for i in range(0, len(companies))]
# Juntamos los resultado con su empresa correspondiente con la función "zip()" \\
# y los convertiremos en un diccionario con la función "dict()"" para ordenarlos más adelante.
sales_stores_companies = dict(zip(companies, sales_stores_relation))
# Ahora ordenaremos de mayor a menor los valores con la función "sorted()" y quitaremos \\
# a Amazon y a Apple incl. Online ya que no cuentan con tiendas físicas.
sales_stores_companies = sorted(sales_stores_companies.items(), key=lambda x: x[1], reverse=True)[:-2]
# Nota 1: Si cambios 'x[1]' por 'x[0]' ordenaremos las llaves en lugar de los valores.
# Nota 2: También podemos importar un módulo en lugar de utilizar una función lambda,
# import operator
# sortedDict = sorted(sales_stores_companies.items(), key=operator.itemgetter(1), reverse=True)
# sortedDict = dict(sortedDict)
# Ya podemos iterar sobre nuestra lista de tuplas \\
# con un ciclo for e imprimirlo en pantalla
print('Top Compañías "dólares por cada tienda": ')
for i, company_list in enumerate(sales_stores_companies):
print("\t{}. {}: ${:,} dólares/tienda".format(i+1, company_list[0], (int(company_list[1] * 1_000_000))))
# Compañías que solamente venden de forma online.
only_online_stores = df[df['Stores'].isna()]
only_online_stores
# Compañías que solamente venden de forma física.
only_physicals_stores = df.dropna()
only_physicals_stores.head(7)
# Promedio de ventas de las tiendas online y físicas.
avg_sales_online_sotres = int(only_online_stores['Sales'].mean())
avg_sales_physicals_stores = int(only_physicals_stores['Sales'].mean())
# Imprimir la comparación dándole formato a la cantidad de ventas y al procentaje.
print("El promedio de ventas de las tiendas en línea es de ${:,} millones de dólares".format(avg_sales_online_sotres))
print("El promedio de ventas de las tiendas físicas es de ${:,} millones de dólares\n".format(avg_sales_physicals_stores))
print("El promedio de las ventas físicas es un {}% más grande que las ventas online (Contando a Walmart US)".format(
round( ((avg_sales_physicals_stores / avg_sales_online_sotres) - 1) * 100, 2) ))
# Hagamos la misma comparación sin Walmart US
avg_sales_online_sotres = int(only_online_stores['Sales'].mean())
avg_sales_physicals_stores = int(only_physicals_stores['Sales'][1:].mean())
# Imprimir la comparación dándole formato a la cantidad de ventas y al procentaje.
print("El promedio de ventas de las tiendas en línea es de ${:,} millones de dólares".format(avg_sales_online_sotres))
print("El promedio de ventas de las tiendas físicas es de ${:,} millones de dólares\n".format(avg_sales_physicals_stores))
print("El promedio de las ventas en línea es un {}% más grande que las ventas físicas (Sin contar a Walmart US)".format(
round( ((avg_sales_online_sotres / avg_sales_physicals_stores ) - 1) * 100, 2) ))
# Ordenaremos nuestro DataFrame por el crecimiento de tiendas
df_sorted_stores_growth = df.sort_values('Store Count Growth', ascending=False)[:5]
df_sorted_stores_growth.head()
# Guardaremos el nombre de la compañía, su categoría y su radio de crecimiento en \\
# tres variable, también empaquetaremos todo con la función "zip()".
top_stores_growth_companies = df_sorted_stores_growth['Company']
top_stores_growth_categories = df_sorted_stores_growth['Category']
top_stores_growth_ratio = round(df_sorted_stores_growth['Store Count Growth'], 3)
top_stores_growth = zip(
top_stores_growth_companies,
top_stores_growth_categories,
top_stores_growth_ratio
)
# Imprimimos con un ciclo for la compañía, su categoría y su crecimiento.
for i, store in enumerate(top_stores_growth):
print("{}. Company: {} - Category: {} - Growth Ratio: {}".format(i+1, store[0], store[1], store[2]))
# Graficamos las 5 empresas con más crecimiento
plt.bar(top_stores_growth_companies, top_stores_growth_ratio)
plt.title('Top 5 Companies with more growth')
plt.xlabel('Company')
plt.ylabel('Growth Ratio')
plt.xticks(rotation=30)
plt.grid(False)
plt.show()
# Haremos lo mismo, pero ahora buscaremos las empresas con menor crecimiento.
df_sorted_stores_ungrowth = df.sort_values('Store Count Growth')[:5]
df_sorted_stores_ungrowth.head()
# Guardaremos el nombre de la compañía, su categoría y su radio de decrecimiento en \\
# tres variable, también empaquetaremos todo con la función "zip()".
top_stores_ungrowth_companies = df_sorted_stores_ungrowth['Company']
top_stores_ungrowth_categories = df_sorted_stores_ungrowth['Category']
top_stores_ungrowth_ratio = round(df_sorted_stores_ungrowth['Store Count Growth'], 3)
top_stores_ungrowth = zip(
top_stores_ungrowth_companies,
top_stores_ungrowth_categories,
top_stores_ungrowth_ratio
)
# Imprimimos con un ciclo for la compañía, su categoría y su decrecimiento.
for i, store in enumerate(top_stores_ungrowth):
print("{}. Company: {} - Category: {} - Growth Ratio: {}".format(i+1, store[0], store[1], store[2]))
# Graficamos las 5 empresas con más decrecimiento
plt.bar(top_stores_ungrowth_companies, top_stores_ungrowth_ratio)
plt.title('Top 5 Companies with less growth')
plt.xlabel('Company')
plt.ylabel('Growth Ratio')
plt.xticks(rotation=30)
plt.grid(False)
plt.show()
# Agrupamos por categoría, sumamos todos los valores.
df_groupedby_categories = df.groupby('Category').sum()
# Ordenamos de menor a mayor y nos quedamos con los primeros 5.
df_groupedby_categories_sorted = df_groupedby_categories.sort_values('Sales')[:5]
df_groupedby_categories_sorted.head()
# Nos quedamos solamente con la categoría y sus ventas y \\
# lo convertimos en un diccionario.
less_profitable_categories_dict = df_groupedby_categories_sorted['Sales'].to_dict()
# Con un ciclo for imprimimos las categorías y sus ventas.
print("Las 5 categorías menos rentables son (Millones de USD):")
for i, (key, value) in enumerate(less_profitable_categories_dict.items()):
print("\t{}.{}: ${:,}".format(i+1, key, value))
# Graficamos con Matplotlib.
plt.bar(less_profitable_categories_dict.keys(), less_profitable_categories_dict.values())
plt.title('Top 5 Categories less profitable')
plt.xlabel('Category')
plt.ylabel('Sales')
plt.xticks(rotation=30)
plt.grid(False)
plt.show()
df_without_walmart = df[1:]
sns.jointplot(data=df_without_walmart, x='Store Count Growth', y='Sales', kind='reg')
plt.title('Sales / Store Count Growth Relation')
plt.show()