Это важно, потому что большинство людей предпочитают смотреть на графики, а не на числа. Таким образом, лучше всего сообщать информацию графически, когда это возможно.
Сначала рассмотрим пример, показывающий, почему описательная статистика так полезна. Предположим, что нам необходимо проанализировать данные по длине чека 128 магазинов розничной торговли в июле 20.. года. Загружаем и смотрим на данные
shop | lch | |
---|---|---|
0 | Sh1 | 3.617 |
1 | Sh2 | 3.513 |
2 | Sh3 | 3.657 |
3 | Sh4 | 3.422 |
4 | Sh5 | 2.760 |
мы сразу видим, что распределение близко к нормальному и при этом есть несколько выбросов, которые скорее всего связаны с ошибкой при загрузке данных.
year | hoody | jacket | pants | shirt | shorts | sweater | t-shirt | |
---|---|---|---|---|---|---|---|---|
0 | 2014 | 174371 | 1379244 | 1539107 | 278161 | 115055 | 370718 | 548600 |
1 | 2015 | 183548 | 1532493 | 1810714 | 319725 | 122399 | 421271 | 583617 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
4 | 2018 | 263796 | 1648123 | 1569927 | 249077 | 101788 | 369063 | 550383 |
5 | 2019 | 320973 | 1504814 | 1465151 | 251654 | 101938 | 290987 | 486544 |
6 rows × 8 columns
Построим круговые диаграммы по годам
for i, (idx, row) in enumerate(df.set_index('year').iterrows()):
ax = axes[i // 3, i % 3]
row = row[row.gt(row.sum()*0.01)]
ax.pie(row, labels=row.index,autopct="%.1f", startangle=30)
ax.set_title(idx)
fig.subplots_adjust(wspace=.2)
По этой диаграмме легко заметить "борьбу" за лидерство двух основных товарных групп - джинсы (pants) и куртки (jacket) и начиная с 2017 года куртки обошли джинсы по доле в годовой выручке.
С гистограммой тесно связан график плотности, который строится на основе оценки непрерывного распределения вероятности по результатам измерений. Обычно стремятся аппроксимировать это распределение комбинацией ядер, т. е. комбинацией более простых распределений, например нормального (гауссова). Поэтому графики плотности еще называют графиками ядерной оценки плотности (KDE – kernel density estimate).
plt.figure(figsize=(10,6))
sns.histplot(df,stat="percent",kde=True)
plt.axvline(df.mean()[0],c="r", linestyle="--")
На этом графике выведена гистограмма длин чека вместе с графиком плотности, вертикальная черта показывает среднее значение. Очевидно, что если исключить выбросы, то распределение нормальное.
Следующий вариант представления информации называется "бохплот", его также называют "ящик с усами"
plt.figure(figsize=(10,6))
sns.boxplot(x=df['lch'])
plt.axvline(df.lch.median(),c="r", linestyle="--")
plt.axvline(df.lch.min(),c="b", linestyle="--")
plt.axvline(df.lch.max(),c="b", linestyle="--")
plt.axvline(df.lch.quantile(0.25),c="r", linestyle="dotted")
plt.axvline(df.lch.quantile(0.75),c="r", linestyle="dotted")
df=pd.read_excel("shops_lch_06_08.xlsx",index_col="date", parse_dates=True)
df
shop | lch | |
---|---|---|
date | ||
2019-06-01 | Sh1 | 3.19 |
2019-06-01 | Sh2 | 3.31 |
... | ... | ... |
2019-08-31 | Sh3 | 2.40 |
2019-08-31 | Sh4 | 2.31 |
368 rows × 2 columns
sns.boxplot(x='shop',y='lch',data=df)
Наконец, давайте посмотрим на данные, состоящие не из одного числа, а из двух, то есть данные поступают парами. Эти данные обычно отображаются в системе координат, которая называется точечной диаграммой. Рассмотрим следующий набор данных : вместе с длиной чека выведены дневные показатели посетителей и выручки для тех же четырех магазинов.
df
Выведем точечную диаграмму для двух показателей - по горизонтальной оси - дневной показатель посетителей, по вертикальной - дневная выручка.
sns.scatterplot(x='visit', y='rev',hue="shop",data=df)
Числовые сводные показатели
Среднее и медианаsale | cheks | lch | |
---|---|---|---|
shop | |||
Sh1 | 1588 | 439 | 3.617 |
Sh2 | 1535 | 437 | 3.513 |
Sh3 | 3555 | 972 | 3.657 |
Sh4 | 3258 | 952 | 3.422 |
Sh5 | 1521 | 551 | 2.760 |
mean = 3.0340 trim mean = 3.0266 median = 3.0258
Взвешенное среднее значение доступно с помощью пакета NumPy. Для взвешенной медианы мы можем использовать специализированный пакет weightedstats, в качестве веса используется количество чеков
import weightedstats as ws
print(f'weighted mean (np) = {np.average(df.lch, weights=df.cheks):.4f}')
print(f'weighted mean (ws) = {ws.weighted_mean(df.lch, weights=df.cheks):.4f}')
print(f'weighted median = {ws.weighted_median(df.lch, weights=df.cheks):.4f}')
weighted mean (np) = 3.0485 weighted mean (ws) = 3.0485 weighted median = 3.0449
DataFrame пакета pandas предоставляет методы для вычисления стандартного
отклонения и квантилей. Используя квантили, мы можем легко определить
межквартильный размах (IQR). Для робастной оценки медианного абсолютного
отклонения (MAD) используем функцию robust.scale.mad из пакета statsmodels:
#не приводит к автоматическому импорту подпакетов (если пакет не написан #для этого явным образом)
import statsmodels.robust
print(f'standard deviation = {df.lch.std():.4f}')
print(f'interquartile range = {df.lch.quantile(0.75) - df.lch.quantile(0.25):.4f}')
print(f'median absolute deviation from the median = {sm.robust.scale.mad(df.lch):.4f}')
standard deviation = 0.4759 interquartile range = 0.3443 median absolute deviation from the median = 0.2658
Комментариев нет:
Отправить комментарий