machinelearningmastery.ru

Машинное обучение, нейронные сети, искусственный интеллект
Header decor

Home

Визуализация Bike Mobility в Лондоне с использованием интерактивных карт и анимации

Дата публикации Jan 7, 2019

фотоМакс АдулянукосолнаUnsplash

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

Отчетыпоказали, что 77% лондонцев согласны с тем, что езда на велосипеде - самый быстрый способ совершить поездку на короткие расстояния. В долгосрочной перспективе это также может помочь увеличить продолжительность жизни в городе.

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

TL; DR - Давайте посмотрим, как мы можем визуализировать систему совместного использования велосипедов, используя графики, карты и анимацию.

Вы можете найти веб-карты на этомстраница, Большинство карт, анимаций и исходных кодов доступны наGitHub, Данные теперь доступны наKaggle,

Оглавление

Первоначально опубликовано в моем блогеedenau.github.io, Моя работа вдохновленаВинсент Лонийа такжеДхрумил Патель, Проверьте их сообщения!


Подробнее о данных - скучный бит

Я получилданныена велосипедных поездках от Транспорт для Лондона (TfL). Каждое путешествие на велосипеде, совершенное в их системе с 2012 года, было зарегистрировано, и эти открытые данные доступныонлайн,

Был проанализирован 36-дневный отчет о поездках, совершенных с 1 августа по 13 сентября 2017 года. За этот период было совершено> 1,5 миллиона поездок между> 700 док-станциями для велосипедов в Лондоне. С 2014 года мы стали свидетелями более чем 190% роста числа поездок на велосипедах. Количество велосипедов и стыковочных станций в системе увеличилось более чем в два раза, чтобы удовлетворить значительный рост спроса на велосипеды в центральном Лондоне и региональных районах. Точные данные будут показаны в моей статье, которая скоро выйдет.Следите за обновлениями,

Манипуляция данными

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

# Load journey dataf = 'journeys.csv'
j = pd.read_csv(f)date = j['date'].values
month = j['month'].values
year = j['year'].values
hour = j['hour'].values
minute = j['minute'].values
station_start = j['id_start'].values
station_end = j['id_end'].values

Затем мы извлекаем данные о дняхdate.weekday()и равномерно разделить 24-часовой день на 72 временных интервала, так что каждый временной интервал представляет 20-минутный интервал.

# Compute IsWeekdayweekday = np.zeros(len(date))
weekday[:] = np.nan
cnt = 0for _year, _month, _date, _hour, _minute in zip(year, month, date, hour, minute):
_dt = datetime.datetime(_year, _month, _date, _hour, _minute)
_weekday = _dt.weekday()
weekday[cnt] = _weekday
cnt += 1IsWeekday = weekday < 5
j['IsWeekday'] = IsWeekday# Compute TimeSlicej['TimeSlice'] = (hour*3 + np.floor(minute/20)).astype(int)

Нам также необходимо проверить, были ли эти поездки на велосипедах с / на упраздненные станции, так как нет способов получить информацию об этих станциях, такую ​​как местоположение, название станции и т. Д. (Хорошая работа TfL). Мы пометили их как «недействительные».

# Load station dataf = 'stations.csv'
stations = pd.read_csv(f)
station_id = stations['station_id'].values# Extract valid journeysvalid = np.zeros(len(date))
valid[:] = False
cnt = 0for _start, _end in zip(station_start, station_end):
if np.logical_and((_start in station_id), (_end in station_id)):
valid[cnt] = True
cnt += 1j['Valid'] = valid

Наконец, мы сохраняем только «действительные» поездкиа такжесделано в будние дни, что составляет около 73% данных.

df = j[j["IsWeekday"] == True].drop(columns="IsWeekday")
df = df[df["Valid"] == True].drop(columns="Valid")print('Ratio of valid journeys= {:.2f}%'.format(df.shape[0] / j.shape[0] * 100))

Гистограммы

Мы наконец углубимся в визуализацию! Простейшими формами визуализации данных являются, возможно, диаграммы. Простымgroupby('TimeSlice')По функции мы можем видеть, как часто совершались поездки в разные часы.

grp_by_timeslice = df.groupby('TimeSlice').count().values[:,0]plt.bar(range(0,72), grp_by_timeslice)
plt.xlabel('Time Slice')
plt.ylabel('Departures')
plt.show()
Средние показатели отправления в будние дни (слева) и в выходные дни (справа)

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

Распределение продолжительности поездки (слева) и скорости (справа)

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


Интерактивные Карты

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

$ pip install folium==0.7.0

(или егоconda installэквивалент). Я работал в Google Colab Laboratory и предустановленная версия0.2.0с минимальными функциональными возможностями.

Я построил простой шаблон для создания карты с маркерами круга (с разными цветами!) С использованием кластеров.

import folium# Change coloursdef color_change(c):
if(c < 15):
return('red')
elif(15 <= c < 30):
return('orange')
else:
return('green')# Create base mapLondon = [51.506949, -0.122876]
map = folium.Map(location = London,
zoom_start = 12,
tiles = "CartoDB positron")
marker_cluster = MarkerCluster(locations=[lat, lon]).add_to(map)# Plot markersfor _lat, _lon, _cap, _name in zip(lat, lon, cap, name):
folium.CircleMarker(location = [_lat, _lon],
radius = 9,
popup = "("+str(_cap)+") "+_name,
fill_color = color_change(_cap),
color = "gray",
fill_opacity = 0.9).add_to(marker_cluster)

f = 'map_station_cluster.html'
map.save(f)

Почему кластеры?MarkerCluster()позволяет маркерам группироваться вместе, когда они находятся слишком близко при уменьшении масштаба Вы не хотите, чтобы ваши карты были слишком грязными, с маркерами, накладывающимися друг на друга.

Карта кластеров станций

Он автоматически раскладывается / разворачивается при увеличении:

Карта кластеров станций - увеличено

Но я обещал тебеинтерактивныйкарты. Вы можете установитьpopupпараметр и отображение названия станции и ее пропускной способности при нажатии на нее. Браво!

Взаимодействия на карте кластера станции

Эта карта доступна наhttps://edenau.github.io/maps/station-cluster/,


Карты плотности

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

def DensityMap(stations, cnt_departure, cnt_arrival):London = [51.506949, -0.122876]

map = folium.Map(location = London,
zoom_start = 12,
tiles = "CartoDB dark_matter")

stations['Total Departure'] = cnt_departure
stations['Total Arrival'] = cnt_arrivalfor index, row in stations.iterrows():
net_departure = row['Total Departure'] - row['Total Arrival']

_radius = np.abs(net_departure)
if np.isnan(_radius):
_radius = 0

if net_departure > 0:
_color= '#E80018' # target red
else:
_color= '#81D8D0' # tiffany blue

lat, lon = row['lat'], row['lon']
_popup = '('+str(row['capacity'])+'/'+str(int(_radius))+') '+row['station_name']

folium.CircleMarker(location = [lat,lon],
radius = _radius,
popup = _popup,
color = _color,
fill_opacity = 0.5).add_to(map)

return map

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

Давайте посмотрим, как выглядят карты плотности в часы пик утром и вечером:

# Select peak hoursTimeSlice = [25,53] # morning and evening
keyword = ['map_morning', 'map_evening']# Journeys depart between 0820 and 0859, and between 1740 and 1819
for ts, kw in zip(TimeSlice, keyword):
df_1 = df[df["TimeSlice"] == ts]
df_2 = df[df["TimeSlice"] == (ts+1)]
df_target = df_1.append(df_2) cnt_departure = df_target.groupby("id_start").count().iloc[:,0]
cnt_arrival = df_target.groupby("id_end").count().iloc[:,0] vars()[kw] = DensityMap(stations, cnt_departure, cnt_arrival)
Карта плотности в утренние часы пик
Карта плотности в вечерние часы пик

Карты плотности доступны наhttps://edenau.github.io/maps/density-morning/а такжеhttps://edenau.github.io/maps/density-evening/,


Карты подключения

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

Карта подключения

Мы также можем добавить несколько слоев соединенияfolium.LayerControl()разделить слои часто и редко используемых путей.

Многослойная карта соединений

Карты подключений доступны наhttps://edenau.github.io/maps/connection-morning/а такжеhttps://edenau.github.io/maps/connection-morning-layers/,


Анимации

До сих пор мы демонстрировали, как визуализировать временную и распределительную информацию с помощью диаграмм, а пространственную информацию - с помощью различных видов карт. Но что, если мы сгенерируем несколько карт в последовательные моменты времени? Мы можем визуализироватьпространственно-временнойинформация с использованием анимации!

Созданные карты являются веб-картами в.htmlфайлы. Идея состоит в том, чтобы:

Создайте карту для каждого экземпляра каждый раз, просмотрите ее в веб-браузере, сделайте снимок экрана и сохраните изображение, а также свяжите все изображения вместе в виде видео или GIF-файла.

Мы собираемся автоматизировать процесс просмотра веб-страниц и захвата экрана с помощьюselenium, Нам также нужен веб-драйвер, и, как пользователь Chrome, я пошел наchromedriver,

from selenium import webdriverdef a_frame(i, frame_time, data):
my_frame = get_image_map(frame_time, data)

# Save the web map
delay = 5 # give it some loading time
fn = 'frame_{:0>5}'.format(i)
DIR = 'frames'
f = DIR + '/' + fn + '.html'
tmpurl='file://{path}/{mapfile}'.format(path=os.getcwd()+
'/frames',mapfile=fn)
my_frame.save(f) # Open the web map and take screenshot
browser = webdriver.Chrome()
browser.get(tmpurl)
time.sleep(delay)
f = DIR + '/' + fn + '.png'
browser.save_screenshot(f)
browser.quit() f = 'frames/frame_{:0>5}.png'.format(i)
image = Image.open(io.BytesIO(f))
draw = ImageDraw.ImageDraw(image)
font = ImageFont.truetype('Roboto-Light.ttf', 30)

# Add text on picture
draw.text((20, image.height - 50),
'Time: {}'.format(frame_time),
fill=(255, 255, 255),
font=font)

# Write the .png file
dir_name = "frames"
if not os.path.exists(dir_name):
os.mkdir(dir_name)
image.save(os.path.join(dir_name, 'frame_{:0>5}.png'.format(i)), 'PNG') return image

Затем мы можем сделать видео или GIFffmpeg, Для пользователя Mac, установкаffmpegможет буквально принять минимальные усилия с помощьюHomebrew, как

Homebrew устанавливаетвещи, которые вам нужнычто Apple не сделала.

После установки Homebrew (с помощью одной команды) просто введите

$ brew install ffmpeg

и вуаля! Чтобы создать.mp4файл, попробуйте

$ ffmpeg -r 10 -i frames/frame_%05d.png -c:v libx264 -vf fps=25 -crf 17 -pix_fmt yuv420p video.mp4

Для.gifфайл, попробуйте

$ ffmpeg -y  -t 3 -i frames/frame_%05d.png \ -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png$ ffmpeg -r 10  -i frames/frame_%05d.png -i palette.png -filter_complex \ "fps=10,scale=720:-1:flags=lanczos[x];[x][1:v]paletteuse" animation.gif

Проверьте анимацию карт плотности в течение дня:

Анимация карт плотности в течение дня

А также анимация путешествий в разное время:

Анимация путешествий по утрам
Анимация путешествий после полуночи

Выводы

Система совместного использования велосипедов в Лондоне визуализируется с помощью гистограмм, карт плотности, карт соединений и анимации.

Абстракция Python делает его действительно хорошим и интересным инструментом для пространственно-временной визуализации данных (за счет вычислительного времени, но неважно). Я использовалfolium,selenium,chromedriver,brew,ffmpegи, самое главное, часть строительных блоков от Винсентакодчтобы это произошло.


замечания

Если вы интересуетесь Python или программированием в целом, вам могут помочь следующие статьи:

Вы выжили бы на Титанике?

Путешествие по непотопляемому - чему ИИ может научиться после катастрофы

hackernoon.com

Краткое руководство по запуску ваших скриптов Python в Google Colab Laboratory

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

towardsdatascience.com

Обработка файлов NetCDF с использованием XArray для начинающих

Изучение инструментов манипулирования данными, связанными с климатом, в Python

towardsdatascience.com

Еще раз, крикВинсент Лонийа такжеДхрумил Пательдля их демонстрации соответствующих работ.

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

Первоначально опубликовано в моем блогеedenau.github.io,

Ссылки

Оригинальная статья

Footer decor

© machinelearningmastery.ru | Ссылки на оригиналы и авторов сохранены. | map