Анализ тенденций продаж с помощью панд

Оценка

Вы только что были приняты на работу в качестве аналитика данных в одну из быстрорастущих компаний по производству и дистрибуции продукции, и ваше первое приветственное задание от MD — создать отчет для предстоящего заседания совета директоров. Вам предстоит просмотреть и проанализировать данные о продажах за 2015-2017 годы, чтобы создать требуемый отчет.

В отчете должно быть отражено следующее;

  1. Выручка по регионам
  2. Выручка по торговым представителям
  3. Доход по продуктам
  4. тенденция продаж
  5. Годовые изменения в выручкеВ отчете следует выделить следующее:
  6. 3 лучших продукта
  7. Наиболее продуктивные торговые представители в соответствующие годы. На основе проведенного анализа дайте 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 года

Вывод/рекомендации:

  1. Лучшими месяцами для продаж являются сентябрь, октябрь и ноябрь. Компании следует рассмотреть возможность создания джинглов в эти периоды для дальнейшего максимизации прибыли.
  2. Сосредоточить целевую аудиторию рекламы на Восточном и Южном регионах.
  3. Наконец, Bellen и Quad продаются больше всего в эти периоды, подумайте о том, чтобы приобрести их больше.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *