Оценка
Вы только что были приняты на работу в качестве аналитика данных в одну из быстрорастущих компаний по производству и дистрибуции продукции, и ваше первое приветственное задание от MD — создать отчет для предстоящего заседания совета директоров. Вам предстоит просмотреть и проанализировать данные о продажах за 2015-2017 годы, чтобы создать требуемый отчет.
В отчете должно быть отражено следующее;
- Выручка по регионам
- Выручка по торговым представителям
- Доход по продуктам
- тенденция продаж
- Годовые изменения в выручкеВ отчете следует выделить следующее:
- 3 лучших продукта
- Наиболее продуктивные торговые представители в соответствующие годы. На основе проведенного анализа дайте 3 рекомендации, которые, по вашему мнению, помогут компании увеличить выручку в следующем году.
Источник данных:
https://docs.google.com/spreadsheets/d/1SWCOO70Yv7PPvmlLyLQj1gCilg1XsSl0/edit?usp=sharing&ouid=102731908679789782364&rtpof=true&sd=true
Код Github: https://github.com/anochima/Sales-Data-Analysis
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Setup our visuals to use seaborn by default
plt.style.use('seaborn')
plt.rcParams["figure.figsize"] = (11, 4)
# Import our data using pandas
df = pd.read_excel('MODULE 2-Assessment working data.xlsx')
# Convert the sales excel file into .csv (Comma Separated Value)
# This is only done because because I feel more comfortable working with Csv files to xlsx files
df = df.to_csv('sales-data.csv', index=False)
# Read the sales data
df = pd.read_csv('sales-data.csv')
df.head()
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Дата | SalesRep | Регион | Продукт | Цвет | Единицы | Выручка | |
---|---|---|---|---|---|---|---|
0 | 2015-11-06 | Джули | Восток | Sunshine | Голубой | 4 | 78.8 |
1 | 2015-11-07 | Адам | Вест | Беллен | Очистить | 4 | 123.0 |
2 | 2015-11-07 | Джули | Восток | Осина | Очистить | 1 | 26.0 |
3 | 2015-11-07 | Набиль | Юг | Quad | Очистить | 2 | 69.0 |
4 | 2015-11-07 | Джули | Юг | Осина | Голубой | 2 | 51.0 |
df.describe(include=['object','float','int'])
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Дата | SalesRep | Регион | Продукт | Цвет | Единицы | Выручка | |
---|---|---|---|---|---|---|---|
счет | 9971 | 9971 | 9971 | 9971 | 9971 | 9971.000000 | 9971.000000 |
уникальный | 717 | 6 | 3 | 7 | 5 | NaN | NaN |
топ | 2016-09-11 | Джули | Запад | Bellen | Красный | NaN | NaN |
freq | 77 | 2233 | 4417 | 1948 | 3020 | NaN | NaN |
среднее | NaN | NaN | NaN | NaN | NaN | 3.388828 | 91.181513 |
std | NaN | NaN | NaN | NaN | NaN | 4.320759 | 120.894473 |
мин | NaN | NaN | NaN | NaN | NaN | 1.000000 | 21.000000 |
25% | NaN | NaN | NaN | NaN | NaN | 2.000000 | 42.900000 |
50% | NaN | NaN | NaN | NaN | NaN | 2.000000 | 60.000000 |
75% | NaN | NaN | NaN | NaN | NaN | 3.000000 | 76.500000 |
max | NaN | NaN | NaN | NaN | NaN | 25.000000 | 1901.750000 |
Некоторые полезные сведения
Всего за период 2015-2017 годов было 9,971
записей о продажах, из которых были сделаны следующие описания:
Единицы:
- Минимальное количество проданных единиц в период 2015-2017 гг. составило
1
. - Максимальное количество проданных единиц в период 2015-2017 гг. составило
25
- Среднее количество проданных единиц в период 2015-2017 гг. составило приблизительно
3
.
Доход
- Наименьший доход за период 2015-2017 гг. составил
21
- Наибольший доход в период 2015-2017 гг. составил приблизительно
1902
—Прочее—
- В период 2015-2017 гг. у нас было
6
уникальных торговых представителей - Мы охватывали
3
региона в период 2015-2017 гг.
# At what amount did we sell most?
df['Revenue'].value_counts().hist(bins=50);
Здесь большинство товаров было продано в диапазоне от 21 до 70 соответственно
df['Units'].hist(bins=50);
# What's the total revenue generated between 2015-2017?
round(df['Revenue'].sum())
909171
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9971 entries, 0 to 9970
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Date 9971 non-null object
1 SalesRep 9971 non-null object
2 Region 9971 non-null object
3 Product 9971 non-null object
4 Color 9971 non-null object
5 Units 9971 non-null int64
6 Revenue 9971 non-null float64
dtypes: float64(1), int64(1), object(5)
memory usage: 545.4+ KB
# Check if we have any missing entry
df.isna().sum()
Date 0
SalesRep 0
Region 0
Product 0
Color 0
Units 0
Revenue 0
dtype: int64
Ни одна запись не пропущена
Доходы по регионам
region_revenue = pd.DataFrame(df.groupby(by=['Region'])['Revenue'].sum())
region_revenue.sort_values(ascending=False, by='Revenue')
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Доходы | |
---|---|
Регион | |
Запад | 408037.58 |
Юг | 263256.50 |
Восток | 237876.79 |
Визуализация влияния на доходы региона
region_revenue.plot(kind='bar', ylabel='Revenue', title='Region revenue impact');
Совершенно очевидно, что Западный регион
принес наибольший доход
Выручка в зависимости от торгового представителя
sales_rep_revenue = df.groupby(by=['SalesRep'])['Revenue'].sum()
sales_rep_revenue = pd.DataFrame(sales_rep_revenue).sort_values(ascending=True, by='Revenue')
sales_rep_revenue
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Выручка | |
---|---|
SalesRep | |
Николь | 92026.68 |
Адам | 102715.60 |
Джессика | 145496.28 |
Набиль | 158904.48 |
Джули | 204450.05 |
Майк | 205577.78 |
Визуализация влияния salesRep на доход
sales_rep_revenue.plot(kind='bar', ylabel='Revenue', title='SalesRep revenue impact');
print('Mike Slightly beat Julie in revenue generation by ' + str(round(((sales_rep_revenue.loc['Mike'] - sales_rep_revenue.loc['Julie']) / sales_rep_revenue.loc['Julie']) * 100, 2))+'%')
Mike Slightly beat Julie in revenue generation by Revenue 0.55
dtype: float64%
Выручка по продуктам
product_revenue = df[['Units', 'Revenue','Product']].groupby('Product').sum().sort_values(ascending=False,by='Units')
product_revenue
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Единицы | Выручка | |
---|---|---|
Продукт | ||
Беллен | 6579 | 168175.05 |
Quad | 6223 | 194032.15 |
Санбелл | 4500 | 114283.09 |
Карлота | 4371 | 101272.05 |
Осина | 4242 | 96382.80 |
Солнечный свет | 4229 | 85983.80 |
Дублеры | 3646 | 149041.93 |
Визуализация влияния продуктов на доход
product_revenue.groupby(by=['Product'])['Revenue'].sum().sort_values(ascending=True).plot(
kind='bar',ylabel='Revenue',title='Product Revenue');
Тенденция продаж
# Convert the date column to a datetime object
df['Date'] = pd.to_datetime(df['Date'])
df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Day'] = df['Date'].dt.day
# df = df.drop('Date',axis=1)
Построение графика/тенденции продаж за год
years = [unique for unique in df.Year.unique()]
years
[2015, 2016, 2017]
def plot_trend(years:list, df):
for year in years:
new_df = df[df['Year'] == year]
new_df.groupby('Date')['Revenue'].sum().plot(linewidth=1.2,
ylabel='Revenue',
xlabel='Date',
title='Sales Trend');
import matplotlib.patches as patches
year1 = patches.Patch(color='blue', label='2015')
year2 = patches.Patch(color='green', label='2016')
year3 = patches.Patch(color='red', label='2017')
plot_trend(years, df)
plt.legend(handles=[year1,year2,year3], loc=2);
График тренда выглядит симметричным для месяцев октябрь в 2017 и 2018 годах соответственно.
Это показывает, что большинство продаж осуществляется в октябре. что могло повлиять на это?
ax = df[['Month', 'Units', 'Revenue']].groupby('Month').sum().plot(
title='Monthly Sales Trend',
ylabel='Revenue',
);
ax.vlines(10,1,300000, linestyles='dashed')
ax.annotate('Oct',(10,0));
Сколько раз был осуществлен вход в каждый месяц?
df['Month'].value_counts().sort_values().plot(kind='bar', xlabel='Month', ylabel='Number of Entries', title='Monthly Entries');
products = pd.DataFrame(df[['Units','Revenue','Product','Month', 'Region']].groupby('Month')['Product'].value_counts())
products
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Продукт | ||
---|---|---|
Месяц | Продукт | |
1 | Bellen | 52 |
Quad | 46 | |
Санбелл | 34 | |
Aspen | 33 | |
Солнечный свет | 33 | |
… | … | … |
12 | Sunbell | 43 |
Осина | 41 | |
Солнечный свет | 36 | |
Карлота | 35 | |
Дублеры | 32 |
84 строки × 1 столбец
products['No_of_products'] = products['Product']
products.drop('Product', inplace=True, axis=1)
products = products.reset_index()
products
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Месяц | Продукт | Кол-во_продуктов | |
---|---|---|---|
0 | 1 | Bellen | 52 |
1 | 1 | Quad | 46 |
2 | 1 | Sunbell | 34 |
3 | 1 | Аспен | 33 |
4 | 1 | Саншайн | 33 |
… | … | … | … |
79 | 12 | Sunbell | 43 |
80 | 12 | Осина | 41 |
81 | 12 | Солнечный свет | 36 |
82 | 12 | Карлота | 35 |
83 | 12 | Дублеры | 32 |
84 строки × 3 столбца
products = products.pivot_table(values=['No_of_products'], index=['Month'], columns=['Product'], aggfunc= np.sum)
products
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead tr th {
text-align: left;
}
.dataframe thead tr:last-of-type th {
text-align: right;
}
Кол-во_продуктов | |||||||
---|---|---|---|---|---|---|---|
Продукт | Осина | Беллен | Карлота | Дублеры | Quad | Солнечный колокольчик | Солнечный свет |
Месяц | |||||||
1 | 33 | 52 | 30 | 29 | 46 | 34 | 33 |
2 | 26 | 45 | 29 | 25 | 45 | 35 | 26 |
3 | 49 | 55 | 46 | 34 | 77 | 35 | 39 |
4 | 31 | 37 | 35 | 27 | 50 | 43 | 25 |
5 | 33 | 52 | 36 | 30 | 51 | 37 | 31 |
6 | 37 | 53 | 23 | 21 | 52 | 30 | 36 |
7 | 38 | 60 | 37 | 25 | 55 | 46 | 42 |
8 | 34 | 54 | 26 | 35 | 51 | 35 | 35 |
9 | 380 | 596 | 399 | 311 | 560 | 397 | 404 |
10 | 476 | 735 | 439 | 333 | 697 | 491 | 460 |
11 | 119 | 154 | 118 | 77 | 142 | 108 | 103 |
12 | 41 | 55 | 35 | 32 | 64 | 43 | 36 |
products.plot(ylabel='No of Products sold', title='Monthly product sales');
Теперь ясно, что мы продаем больше Bellen
в течение октября, и это и ОЧЕНЬ большие продажи начинаются между сентябрем и концом ноября
.
Ежемесячный доход региона
region_sales = pd.DataFrame(df[['Units','Revenue','Product','Month', 'Region']]).groupby(['Month','Region'])['Revenue'].sum()
region_sales = pd.DataFrame(region_sales)
region_sales
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Доход | ||
---|---|---|
Месяц | Регион | |
1 | Восток | 5012.34 |
Юг | 7551.55 | |
Запад | 8550.33 | |
2 | Восток | 6428.75 |
Юг | 5540.10 | |
Запад | 10864.87 | |
3 | Восток | 6082.75 |
Юг | 8863.80 | |
Запад | 14087.99 | |
4 | Восток | 6420.63 |
Юг | 7647.28 | |
Запад | 8865.57 | |
5 | Восток | 8782.68 |
Юг | 5651.30 | |
Запад | 10962.00 | |
6 | Восток | 6442.85 |
Юг | 3954.90 | |
Запад | 9020.65 | |
7 | Восток | 7180.45 |
Юг | 10155.59 | |
Запад | 10150.25 | |
8 | Восток | 6031.55 |
Юг | 7767.60 | |
Запад | 11567.37 | |
9 | Восток | 70532.44 |
Юг | 83228.39 | |
Запад | 127160.06 | |
10 | Восток | 87858.60 |
Юг | 92034.70 | |
Запад | 151780.43 | |
11 | Восток | 19478.10 |
Юг | 24048.59 | |
Запад | 33196.52 | |
12 | Восток | 7625.65 |
Юг | 6812.70 | |
Запад | 11831.54 |
region_sales = region_sales.reset_index()
region_sales = region_sales.pivot_table(values=['Revenue'], index=['Month'], columns=['Region'], aggfunc= np.sum)
region_sales
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead tr th {
text-align: left;
}
.dataframe thead tr:last-of-type th {
text-align: right;
}
Доходы | |||
---|---|---|---|
Регион | Восток | Юг | Запад |
Месяц | |||
1 | 5012.34 | 7551.55 | 8550.33 |
2 | 6428.75 | 5540.10 | 10864.87 |
3 | 6082.75 | 8863.80 | 14087.99 |
4 | 6420.63 | 7647.28 | 8865.57 |
5 | 8782.68 | 5651.30 | 10962.00 |
6 | 6442.85 | 3954.90 | 9020.65 |
7 | 7180.45 | 10155.59 | 10150.25 |
8 | 6031.55 | 7767.60 | 11567.37 |
9 | 70532.44 | 83228.39 | 127160.06 |
10 | 87858.60 | 92034.70 | 151780.43 |
11 | 19478.10 | 24048.59 | 33196.52 |
12 | 7625.65 | 6812.70 | 11831.54 |
region_sales.plot(kind='bar', ylabel='Revenue', title='Region Monthly Revenue');
Годовые изменения выручки
changes = pd.DataFrame(df.groupby([df.Date.dt.year])['Revenue'].sum())
changes
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Выручка | |
---|---|
Дата | |
2015 | 24883.84 |
2016 | 444701.72 |
2017 | 439585.31 |
changes.sort_values('Date').plot(kind='bar');
Топ-3 продуктов
product_revenue
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Единицы | Выручка | |
---|---|---|
Продукт | ||
Беллен | 6579 | 168175.05 |
Quad | 6223 | 194032.15 |
Санбелл | 4500 | 114283.09 |
Карлота | 4371 | 101272.05 |
Осина | 4242 | 96382.80 |
Солнечный свет | 4229 | 85983.80 |
Дублеры | 3646 | 149041.93 |
Наши 3 лучших продукта — Bellen, Quad и Sunbell
.
Самый продуктивный торговый представитель в соответствующие годы. На основе проведенного анализа дайте 3 рекомендации, которые, по вашему мнению, помогут компании увеличить доход в следующем году.
salesReps = df[['SalesRep','Year','Revenue','Units']]
salesReps = pd.DataFrame(salesReps.groupby(['Year','SalesRep'])['Revenue'].sum())
salesReps.sort_values(by=['Year','Revenue'], ascending=False)
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Выручка | ||
---|---|---|
Год | SalesRep | |
2017 | Джули | 99727.32 |
Майк | 96062.19 | |
Набиль | 81079.23 | |
Джессика | 69479.74 | |
Адам | 49712.19 | |
Николь | 43524.64 | |
2016 | Майк | 104590.64 |
Джули | 98895.58 | |
Набиль | 74576.22 | |
Джессика | 71469.42 | |
Адам | 49184.21 | |
Николь | 45985.65 | |
2015 | Джули | 5827.15 |
Майк | 4924.95 | |
Джессика | 4547.12 | |
Адам | 3819.20 | |
Набиль | 3249.03 | |
Николь | 2516.39 |
Джули выделяется по доходам от продаж ежегодно, за исключением 2016 года
Вывод/рекомендации:
- Лучшими месяцами для продаж являются сентябрь, октябрь и ноябрь. Компании следует рассмотреть возможность создания джинглов в эти периоды для дальнейшего максимизации прибыли.
- Сосредоточить целевую аудиторию рекламы на
Восточном и Южном регионах
. - Наконец, Bellen и Quad продаются больше всего в эти периоды, подумайте о том, чтобы приобрести их больше.