Как выбор правильного цвета и масштабов может сделать или сломать ваше сообщение (с примерами и кодом Python)

Возможно, вы видели эту карту COVID, о которой сначала сообщил andishenouraee в Твиттере, а затем она была освещена в средствах массовой информации.

Даже если да, взгляните еще раз. Если нет, то это картограммы, на которых показаны случаи заболевания Covid-19 в каждом округе (с июля 2020 года) в штате Джорджия. Две карты кажутся очень похожими, но наблюдатели среди вас могли заметить одно существенное различие - масштаб.

Изменения шкалы маскируют тот факт, что каждая цветная полоса примерно на 50% выше, и многие из областей с одинаковым цветом на самом деле в той же шкале будут на оттенок темнее на правом изображении.

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

Да и еще - эти чешуйки выглядят странно! Числа, определяющие эти диапазоны, весьма нерегулярны. Давайте просто визуализируем данные. Мы можем установить цветовые полосы на те же цвета, что и карта, чтобы создать столбчатую диаграмму с накоплением:

bands_df = pd.read_csv("srcdata/colormap_1.csv")
fig = px.bar(bands_df, x="Width", y="Type", color="Band", barmode="stack", template="plotly_white",
             color_discrete_sequence=["#e9f3fa", "#9cbfe9", "#74a6e1", "#4182d6", "#2d5a95", "#c8281c"])
fig.update_layout(bargap=0.4)
fig.show()

Нижняя полоса показывает масштаб на «старой» карте, а верхняя полоса - «новая» карта с более свежими данными.

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

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

И наоборот, каждую визуализацию данных следует просматривать при включенном детекторе BS и осознавать, что сообщение может содержать дезинформацию.

Давайте рассмотрим еще несколько примеров того, как шкала цветов может изменить сообщение, доставляемое визуализацией.

Здесь я буду использовать несколько модифицированных примеров моих картографических данных из этой статьи ниже. Если вы хотите продолжить, исходная статья представляет набор данных и код в связанном репозитории git, а новый код содержится в colourscale.py. Я покажу исправленный код там, где он может быть уместным.



Застряли в середине

Важность средних точек в расходящихся шкалах

Мне, наверное, не нужно говорить, что автоматическое масштабирование обычно не то, что нам нужно. Вот карта с автоматическим масштабированием.

Он показывает некоторые контуры, но на карте преобладают оранжевые / красные цвета, хотя вся шкала цветов охватывает переходы от синего / желтого / красного. Вот еще один подход.

На этой карте нанесен диапазон от 0 до 100 000 долларов США, исходя из того факта, что среднее значение типичных доходов округов составляет около 50 000 долларов США. Конечным результатом является карта, на которой округа США делятся на две половины, на которой синим цветом показаны 50% округов с самыми высокими доходами, а красным - другая половина.

Сравните это с картой ниже, где середина цветовой шкалы теперь является общим медианным доходом домохозяйства в США.

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

Что это показывает?

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

Это простое, но важное изменение.

Давайте взглянем на еще несколько существенных изменений.

Что, если бы мы просто хотели знать, какие округа самые богатые, а какие самые бедные?

Относительные шкалы и цвета

Прежде всего нам нужно переставить данные. Здесь можно использовать метод .rank() для генерации ранга данных из столбца, например дохода, например:

data_df["Median_Household_Income_2018"].rank())

Это создаст ранг, в котором уезды с самым высоким доходом будут иметь самый высокий «ранг». Для наглядности давайте инвертируем это и назначим новому столбцу:

data_df = data_df.assign(inc_rank=data_df["Median_Household_Income_2018"].rank(ascending=False))

Итак, теперь мы можем построить данные:

fig = px.choropleth_mapbox(data_df, locations="fips", color="inc_rank", geojson=counties, color_continuous_scale=px.colors.diverging.RdYlBu, labels=labels)

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

Вместо этого давайте использовать последовательную шкалу цветов.

fig = px.choropleth_mapbox(data_df, locations="fips", color="inc_rank", geojson=counties, color_continuous_scale=px.colors.sequential.Greens_r, labels=labels)

В результате чего:

Лучше! Он чище, вас не отвлекает бессмысленная середина или изменение оттенка без причины.

Как бы эта диаграмма выглядела с некоторыми другими последовательными цветовыми шкалами? Взгляните на эти примеры в разной цветовой гамме:

fig = px.choropleth_mapbox(data_df, locations="fips", color="inc_rank", geojson=counties, color_continuous_scale=COLORSCALE_HERE, labels=labels)

Каждый из них изменяет тон изображения и сопутствующего сообщения, даже если данные точно такие же. Как влияет использование «холодного» цвета, такого как синий, или «теплого» цвета, например красного, для затенения? Красный, например, больше вызывает воспоминания. Это то, что вы хотите?

Вы хотите выбрать более темный цвет для обозначения регионов с более низким социально-экономическим положением? А как насчет того, чтобы использовать для них красный или синий? Может ли ассоциация вызвать эмоциональную реакцию (намеренную или нет) и отвлечь внимание от сообщения?

Цветовая палитра - огромная тема, и я даже не имею достаточной квалификации, чтобы говорить о ней, но обязательно изучите различные варианты и то, как они «ощущаются».

Масштабирование цветовой шкалы

Остановимся и поговорим о том, какую информацию мы стремимся предоставить. Мы ранжировали округа как есть, но они: а) не одинакового размера и б) имеют огромные различия в плотности населения. Взгляните на эту диаграмму, показывающую различия в размерах населения в округах.

fig = px.histogram(data_df, x="Median_Household_Income_2018", nbins=20, labels=labels, color_discrete_sequence=px.colors.qualitative.Safe,
template="plotly_white", title="Histogram of counties' populations")
fig.show()

Он простирается до городов с населением более 10 миллионов человек, в то время как большая часть населения проживает в округах с населением менее 200 тысяч человек. Что, если мы посмотрим на данные в логарифмической шкале? Plotly позволяет строить график в логарифмическом масштабе, но мы также можем сгенерировать новый столбец, где он будет преобразован в логарифмический масштаб:

fig = px.histogram(data_df, x="pop_log", nbins=20, labels=labels,
color_discrete_sequence=px.colors.qualitative.Safe, template="plotly_white", title="Histogram of counties' populations")
fig.show()

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

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

fig = px.scatter(data_df, x="inc_rank", y="Median_Household_Income_2018", labels=labels,
                 size="POP_ESTIMATE_2018", template="plotly_white")
fig.show()

Итак, давайте масштабируем нашу цветную карту, чтобы учесть население округа. Я сделал это таким образом, чтобы определить ранги, а затем заново скорректировать значение процентиля в соответствии с размерами населения. Фрагмент кода находится здесь:

data_df = data_df.assign(inc_percentile=data_df["Median_Household_Income_2018"].rank(pct=True, ascending=False) * 100)
total_pop = data_df["POP_ESTIMATE_2018"].sum()
data_df = data_df.assign(pop_inc_percentile=data_df["inc_percentile"].apply(lambda x: data_df[data_df["inc_percentile"] <= x]["POP_ESTIMATE_2018"].sum()/total_pop * 100))

Результирующий график (так же, как и раньше) рисуется как таковой:

fig = px.choropleth_mapbox(data_df, locations="fips", color="pop_inc_percentile", geojson=counties, color_continuous_scale=px.colors.sequential.Greens_r, labels=labels)

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

Интересно, правда?

Учитывая то, что мы смогли сделать с этими небольшими изменениями, неудивительно, что бесчисленные изменения могут представлять данные таким образом, который сильно отличается друг от друга. Эти изменения, в свою очередь, могут вызвать у читателя совершенно разные впечатления, независимо от того, предназначались они или нет.

И это даже без изменения цветовой шкалы на странные нелинейные шкалы, как показано на нашей первой диаграмме. (Я не думаю, что буду повторять это, потому что не могу представить, когда это действительно будет полезно.)

Итак, как я уже упоминал выше - помните, как представлены цвета, а также следите за тем, как другие представляют данные.

Непосредственно перед отъездом - если вам это понравилось, поздоровайтесь / подпишитесь на Twitter или следите за обновлениями.

Изменить: я запускаю Подстек для всего, что связано с данными и визуализацией - это будет способ взаимодействовать с вами напрямую. . Я хотел бы, чтобы вы присоединились ко мне здесь.



Еще я написал немного о том, почему я запускаю подстек.

Если вам понравилась эта статья, ознакомьтесь с этими статьями!