Блочные диаграммы всегда были одним из моих любимых способов просмотра данных, потому что они лучше всего подходят для сравнения распределений между группами. Они компактны в своем обобщении данных, и легко сравнивать группы по положению маркировки прямоугольника и усов.
Я думаю, что при создании блочных диаграмм это также очень важный шаг — отображать базовые исходные точки данных, когда это возможно. Это лучший способ одновременно обобщить данные и позволить читателю прийти к их интерпретации.
В этом посте мы будем использовать Seaborn для создания основных сюжетов с небольшими изменениями, чтобы сделать его более привлекательным.
Что такое блок-сюжет?
Блочная диаграмма создается путем вычисления квартилей набора данных, которые делят диапазон чисел на четыре части в зависимости от их распределения.
- Минимум: Q1–1,5*IQR
- 1-й квартиль (Q1): 25-й процентиль
- Медиана: 50-й процентиль
- 3-й квартиль(Q3): 75-й процентиль
- Максимум: 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)
Это тоже выглядит очень здорово, но все зависит от ваших личных предпочтений.
Наконец, хотя это и не сделано в этом посте, усовершенствование меток осей, добавление заголовка и подзаголовка — это также то, что сделает блок-график более презентабельным и достойным публикации.