Блочные диаграммы всегда были одним из моих любимых способов просмотра данных, потому что они лучше всего подходят для сравнения распределений между группами. Они компактны в своем обобщении данных, и легко сравнивать группы по положению маркировки прямоугольника и усов.

Я думаю, что при создании блочных диаграмм это также очень важный шаг — отображать базовые исходные точки данных, когда это возможно. Это лучший способ одновременно обобщить данные и позволить читателю прийти к их интерпретации.

В этом посте мы будем использовать Seaborn для создания основных сюжетов с небольшими изменениями, чтобы сделать его более привлекательным.

Что такое блок-сюжет?

Блочная диаграмма создается путем вычисления квартилей набора данных, которые делят диапазон чисел на четыре части в зависимости от их распределения.

  1. Минимум: Q1–1,5*IQR
  2. 1-й квартиль (Q1): 25-й процентиль
  3. Медиана: 50-й процентиль
  4. 3-й квартиль(Q3): 75-й процентиль
  5. Максимум: Q3+1,5*IQR

Здесь IQR представляет собой межквартильный диапазон, который начинается с первого квартиля (Q1) и заканчивается третьим квартилем (Q3).

Данные

Для начала давайте посмотрим, с какими данными мы работаем. Мне удалось получить набор данных ежегодного анонимного опроса о зарплатах в сфере ИТ для европейского региона. Этот набор данных содержит много информации об ИТ-специалистах рабочего класса, поэтому в нем много столбцов.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv(r"C:\IT Salary Survey EU  2020.csv")
df

Но я использовал статистику только для специалистов по данным, инженеров и аналитиков.

df_new = df.loc[df['Position '].isin(['Data Analyst', 'Data Engineer', 'Data Scientist'])]
df_new

Seaborn по умолчанию с Panda

Если честно, использование Seaborn по умолчанию не так уж и плохо, но его всегда можно сделать лучше.

plt.subplots(figsize=(15, 7.5), dpi =200)
sns.set(style = "white")

sns.boxplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender',linewidth=2.5, fliersize=0)
plt.show()

Выглядит достаточно прилично, да. Но, как я сказал вначале, очень важно также отображать исходные точки исходных данных, когда это возможно. Вот почему я вызываю stripplot, чтобы показать необработанные данные.

plt.subplots(figsize=(15, 7.5), dpi =200)
sns.set(style = "white")

sns.boxplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender',linewidth=2.5, fliersize=0)
sns.stripplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR', hue ='Gender')
plt.show()

На мой взгляд, самый простой способ улучшить ваши сюжеты — изменить стиль морского побережья на белый, если он еще не установлен, а также передать цветовую палитру в зависимости от различных факторов, таких как ваша аудитория или личный вкус.

plt.subplots(figsize=(15, 7.5), dpi =200)
sns.set(style = "white")
pal = sns.color_palette('Paired')


sns.boxplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender',linewidth=2.5, fliersize=0, palette = pal)
sns.stripplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR', hue ='Gender', palette = pal)
plt.show()

Вы также можете указать нужные цвета для каждого значения оттенка.

plt.subplots(figsize=(15, 7.5), dpi =200)
sns.set(style = "white")
pal = my_pal = {"Female": "g", "Male": "b"}


sns.boxplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender',linewidth=2.5, fliersize=0, palette = pal)
sns.stripplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR', hue ='Gender', palette = pal)
plt.show()

Подробнее...

Это также удобно, над этим все еще можно работать. Если мы хотим, чтобы это выглядело лучше, нам придется углубиться в детали.

When you start digging into the parameters, it's a good idea
# to explicitly initialize the figure and get the figure and
# axes handles
fig, ax = plt.subplots(figsize=(15, 7.5), dpi =200)

# First, we'll pick some nicer colors for the Male and Female.
# I got these colors from the color picker online.
dark_blue='#161bb2'
dark_pink='#b2165c'
pal = {'Male': dark_brown, 'Female': dark_pink}

# Here, we set up some properties for the boxplot parts.I borrowed this from stackoverflow
boxprops = {'edgecolor': 'k', 'linewidth': 2, 'facecolor': 'w'}
lineprops = {'color': 'k', 'linewidth': 2}

# Set up some general kwargs that we'll use in both the stripplot and boxplot
# Note that you can change the order of hue variables here.
kwargs = {'palette': pal, 'hue_order': ['Male', 'Female']}

# The boxplot kwargs get passed to matplotlib's boxplot function.
# Note how we can re-use our lineprops dict to make sure all the lines
# match. You could also edit each line type (e.g. whiskers, caps, etc)
# separately.
boxplot_kwargs = dict({'boxprops': boxprops, 'medianprops': lineprops,
                       'whiskerprops': lineprops, 'capprops': lineprops,
                       'width': 0.75},
                      **kwargs)
stripplot_kwargs = dict({'linewidth': 0.6, 'size': 6, 'alpha': 0.7},
                        **kwargs)

# And we can plot just like last time
sns.boxplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender', ax=ax,
    fliersize=0, **boxplot_kwargs)
sns.stripplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender', ax=ax,
    dodge=True, jitter=0.2, **stripplot_kwargs)

Хотя это мой наиболее предпочтительный вид, мы можем решить добавить цвета лица. Мы делаем это, вызывая ключевое слово палитры в функции seaborn.

# When you start digging into the parameters, it's a good idea
# to explicitly initialize the figure and get the figure and
# axes handles
fig, ax = plt.subplots(figsize=(15, 7.5), dpi =200)

# First, we'll pick some nicer colors for the Male and Female.
# I got these colors from the color picker online.
dark_blue='#161bb2'
dark_pink='#b2165c'
pal = {'Male': dark_brown, 'Female': dark_pink}

# Here, we set up some properties for the boxplot parts.I borrowed this from stackoverflow
boxprops = {'edgecolor': 'k', 'linewidth': 2, 'facecolor': 'w'}
lineprops = {'color': 'k', 'linewidth': 2}

# Set up some general kwargs that we'll use in both the stripplot and boxplot
# Note that you can change the order of hue variables here.
kwargs = {'palette': pal, 'hue_order': ['Male', 'Female']}

# The boxplot kwargs get passed to matplotlib's boxplot function.
# Note how we can re-use our lineprops dict to make sure all the lines
# match. You could also edit each line type (e.g. whiskers, caps, etc)
# separately.
boxplot_kwargs = dict({'boxprops': boxprops, 'medianprops': lineprops,
                       'whiskerprops': lineprops, 'capprops': lineprops,
                       'width': 0.75},
                      **kwargs)
stripplot_kwargs = dict({'linewidth': 0.6, 'size': 6, 'alpha': 0.7},
                        **kwargs)

# And we can plot just like last time
sns.boxplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender', ax=ax,
    fliersize=0, **boxplot_kwargs)
sns.stripplot(data= df_new, x= 'Position ', y= 'Annual Salary in EUR',hue = 'Gender', ax=ax,
    dodge=True, jitter=0.2, **stripplot_kwargs)

Это тоже выглядит очень здорово, но все зависит от ваших личных предпочтений.

Наконец, хотя это и не сделано в этом посте, усовершенствование меток осей, добавление заголовка и подзаголовка — это также то, что сделает блок-график более презентабельным и достойным публикации.