"Начиная"

Mad Maps - визуализация географических данных для максимального воздействия

Как эффективно передавать данные на картах для ясного и глубокого понимания с помощью Python (включая код и данные)

Президентские выборы в США снова приближаются. У вас, без сомнения, уже были карты, наводнившие вашу ленту новостей и ленту новостей в Твиттере, и в следующие несколько недель после 3 ноября это станет более частым.

В наши дни мы воспринимаем карты как должное, и нетрудно понять, почему. Смартфоны оснащены технологией, позволяющей точно определять местонахождение нас и указывать маршрут до 5 ближайших японских ресторанов с рейтингом не ниже 4,0. Карты никогда не были так интегрированы в нашу жизнь, хотя всего десять лет назад люди все еще использовали уличные справочники. (Вздрагивает)

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

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

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

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

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

Перенесемся в наши дни, существуют удивительные инструменты визуализации данных (такие как Plotly, DataWrapper или Tableau), которые могут создавать карты, которые не только наполнены информацией, но и визуально поражают.

В качестве примера взгляните на это изображение сельскохозяйственных культур, выращиваемых в Соединенных Штатах:

Или эту карту поддержки доходов, предоставляемой различными правительствами во время пандемии:

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

Прежде чем мы начнем

Чтобы продолжить, установите plotly, pandas и numpy. Установите каждый (в виртуальной среде) с помощью простого pip install [PACKAGE_NAME].

Импортируйте соответствующие модули с помощью:

import pandas as pd
import numpy as np
import plotly.express as px

Здесь вы можете найти все необходимые данные и код (посмотрите файл draw_map.py):



Наши первые карты

Загрузить данные базовой карты

В этой статье мы нанесем данные на карту Соединенных Штатов на уровне округа. Для этого нам понадобится макет базового набора данных с местоположениями округов. Давайте воспользуемся рекомендованным Plotly файлом GeoJSON:

from urllib.request import urlopen
import json
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

Загрузите данные

Один легко доступный набор данных на уровне округа - это доход. Я предварительно обработал набор данных (из переписи населения США) и сохранил его во фрейме данных, поэтому просто загрузите его вот так:

data_df = pd.read_csv("srcdata/proc_data.csv", index_col=0)

Чтобы убедиться, что он включает соответствующие данные и нужное количество строк / столбцов, выполнив такие команды, как data_df.head(), data_df.info():

(Фрейм данных должен включать 3223 строки, и каждая строка должна включать код FIP.)

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

Вот мой пример:

То, что я здесь делаю, довольно просто. Данные передаются как первый аргумент (data_df); из которых столбец fips и столбец Median_Household_Income_2018 передаются в качестве данных местоположения и цвета соответственно; а переменная counties - это наши данные GeoJSON, которые мы загрузили ранее.

Методы update_layout и update_traces используются из эстетических соображений; установка стиля карты, уровня масштабирования, местоположения и полей рисунка.

Вы могли заметить, что я установил здесь диапазон цветов от 0 до 100 000. Я выбрал это значение, поскольку 50 000 - это примерно среднее значение для набора данных. Он разработан для того, чтобы эти «средние» значения выглядели как можно более нейтральными.

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

Изменить: Вот некоторые вещи, которые суперполезный Redditor смог выбрать, просто взглянув на карту (полный комментарий здесь):

Видите ту крохотную голубую точку на севере Нью-Мексико? Это округ Лос-Аламос. В него входят два города, экономика которых вращается вокруг местной национальной лаборатории, в которой работают тысячи ученых и инженеров. В Лос-Аламосе самое большое количество докторов наук на душу населения среди всех округов.

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

Это оранжевое пятно в восточной части Кентукки и южной части Западной Вирджинии - это уволенные угольщики и жители Аппалачей, живущие в бедности.

Оранжевые пятна в Южной Дакоте и районе Четырех углов - это резервации коренных американцев. Эти места неизменно больше всего страдают от бедности.

Виден Черный пояс вдоль дельты Миссисипи и на глубоком юге. Сельские афроамериканцы изо всех сил пытаются свести концы с концами и непропорционально сильно страдают от СПИДа, диабета и ожирения.

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

Сделаем еще один шаг вперед. Что, если бы мы хотели определить определенную демографическую группу, например, округа с низкими или высокими доходами? Мы можем получить некоторое представление об этой карте, но мы можем сделать лучше.

Один из способов добиться этого - фильтровать фрейм данных. Поскольку Plotly просто игнорирует отсутствующие точки данных (как вы могли заметить выше с одним неокрашенным округом), нам даже не нужно заменять отсутствующие значения заполнителями.

Вы заметите, что код более или менее точно такой же. Единственное, что я здесь сделал иначе, - это отфильтровать данные и передать отфильтрованный фрейм данных. И вуаля!

И мы можем внести аналогичные изменения в график графств с высоким доходом.

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

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

Что я здесь сделал, так это сжал диапазон (от 20 000 до 40 000), а затем изменил цветовую шкалу на последовательную (оранжевую), перевернув ее так, чтобы нижние цвета были темнее. Ниже приведен результат:

То же самое и с округами с более высоким доходом, но с синими цветами и несвязанными цветами (так что это естественно выходит за пределы набора данных).

С помощью этих графиков действительно можно выделить округа с самым низким и самым высоким доходом.

Больше, чем пони с одним трюком

Но какие еще шаблоны могут существовать? Именно здесь хороплетные карты начинают проявлять свои ограничения. Он позволяет нанести только одну переменную на фиксированную область.

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

Мы могли бы, например, разделить округа по квартилям с помощью функции pd.qcut:

x = pd.qcut(tmp_df["POP_ESTIMATE_2018"], 4)

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

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

Итак, как мы можем нанести такие данные на конкретную географию?

Дело не только в размере

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

Это может быть немного абстрактно, так что вот реальный пример. Это карта графств мира. Мы все видели это бесчисленное количество раз:

А вот и мир, границы которого масштабировались населением. Обратите внимание, как некоторые места, такие как моя родная страна (Австралия), канули в лету, в то время как другие, такие как Индония, теперь намного, намного больше.

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

Вместо этого давайте построим пузырьковую диаграмму. Я большой поклонник пузырьковых диаграмм; это позволяет нам представить другое измерение данных с размерами пузырьков.

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

Пузыри на поверхности

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

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

По сути, данные представлены в виде вложенных списков (в словарях), поэтому этот скрипт просматривает список, чтобы получить нижнюю левую (min, min) границу и правую верхнюю границу (max, max). Затем мы собираем центр коробки и строим фрейм данных вместе с кодом FIP.

У вас должен получиться county_df, который выглядит так:

С этого момента нужно просто получить данные о доходах и населении и построить график.

Я решил сделать это здесь, используя метод .join, а затем просто нанесу данные на график. Обратите внимание, что функция Ploty Express, которую я здесь использую, scatter_mapbox, а не choropleth_mapbox, но все здесь должно быть довольно понятным.

Единственное, с чем мне пришлось повозиться, это атрибут size_max; что более или менее зависит от личных предпочтений.

И мы получаем этот великолепно выглядящий график:

Я сжал диапазоны здесь для визуального впечатления; но картина кардинально отличается от приведенной выше, на которой, по сути, представлены те же данные, без учета численности населения. Взгляните на это сравнение:

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

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

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

И как читателям, возможно, стоит подумать, действительно ли выводы, которые вы можете сделать из визуального представления, оправданы.

Небольшое примечание, но я думаю, что это очень важно в нашем визуальном мире.

Если вам понравилось, поздоровайтесь / подпишитесь на twitter или следите за обновлениями. ICYMI: Я также написал эту статью о Streamlit и Dash, двух очень популярных пакетах для создания онлайн-панелей с помощью Python.



А вот еще одна статья с визуализацией географических данных - на этот раз визуализация путешествий по НБА!



Оставайтесь в безопасности; и увидимся в следующий раз!