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


Схема метро 1993 года, и выполненная в той же стилистике современная
Визуальная стилистика проекта вдохновлена эстетикой дизайна старых схем метро. Это простая и достаточно лаконичная стилистика, благодаря чему она хорошо подходит для иллюстрации статистических данных.
В исследовании использованы данные с Портала открытых данных правительства Москвы. Датасет содержит статистические данные по количеству вошедших и вышедших пассажиров для каждой станции московского метро на каждый квартал 2021–2025 годов, а так же информацию о названии станции и принадлежности к линии.
В анализе были использованы все данные содержащиеся в датасете, за исключением технической информации (внутрипортальные id и прочее). Данные представлены в виде csv таблицы.
Особенности анализа
Для анализа были использованы различные виды графиков.
Столбчатые диаграммы оказались хорошим способ визуализации статистики по станциям одной линии, хорошо заметны контрасты в входящих пассажирах между разными станциями.
Точечные диаграммы позволили показать и входящих пассажиров, и выходящих. Это позволяет не только отсортировать станции по «популярности», но и найти аномалии.
Круговые диаграммы позволяют качественно визуализировать узнать долю каждой из линий в общем количестве входящих пассажиров.
Линейные хорошо подошли для изучения долгосрочных трендов, этот тип позволяет отображать изменения сразу множества линий на одном графике.
В исследовании была использована библиотека Pandas для работы визуализации csv-файлов, matplotlib.pyplot для построения графиков.
Обработка данных
В начале анализа мною были импортированы необходимые библиотеки, загружен датасет. Из датасета мы загружаем только столбцы содержащие ценные данные. Здесь же выставляется шрифт и базовые цвета.
import pandas as pd import matplotlib.pyplot as plt
df_PT = pd.read_csv ('data/PassengerTraffic.csv', delimiter = '; ', skiprows = 1, usecols = ['Станция метрополитена', 'Линия', 'Год', 'Квартал', 'Входы пассажиров', 'Выходы пассажиров']) # скипаем техничсекую строчку и забираем только нужные там столбцы
bg = '#fdfced' text_color = '#000000' colums = '#f0162f' fnt = 'Futura Md BT [Rus by me]'
Визуализируем первый график. Для этого вытаскиваем из изначального датафрейма данные только за 2025 год и только по станциям Арбатско-Покровской линии. На данном этапе мы имеем по 4 строчки значений для каждой станции — по одной строке на квартал. Группируем значения чтобы получить статистику за год. Строим столбики.
colums = '#017bc4'
берём значения только за один год и только по одной линии newDF = df_PT[ (df_PT['Год'] == 2025) & (df_PT['Линия'] == 'Арбатско-Покровская линия') ]
собираем датафрейм для визуализации diagram1DF = ( newDF.groupby ('Станция метрополитена', as_index=False)['Входы пассажиров'].sum () # уюираем повторы и суммируем )
делаем график столбчатая диагармма по 2 значениям diagram1DF.plot (kind='bar', x='Станция метрополитена', y='Входы пассажиров', width=1, facecolor = colums, legend=False)
plt.xlabel ('Станции', color = text_color, fontname = fnt) # заголовок горизонтальный plt.xticks (rotation=60, color = text_color, fontname = fnt) # поворот заголовка plt.ylabel ('Млн. человек', color = text_color, fontname = fnt) # заголовок вертикальный plt.title ('Колличество входов пассажиров за 2025 год на Арбатско-Покровской линии', color = text_color, fontname = fnt) # название plt.grid (True, alpha = 0.2)
обозначаем пассажиров в миллионах plt.gca ().yaxis.set_major_formatter ( plt.FuncFormatter (lambda x, _: f'{x/1000000:.0f}') )
plt.show () # показываем эту штуку
Строим второй график. меняем цвет будущих точек на цвет линии — зеленый. Повторяем манипуляции с кодом, чтобы получить значения по входящим пассажирам на каждую станцию за год. Строим на основе данных точечную диаграмму.
colums = '#4abd62'
берём значения только за один год newDF2 = df_PT[ (df_PT['Год'] == 2025) & (df_PT['Линия'] == 'Замоскворецкая линия') ]
собираем датафрейм для визуализации, как в прошлый раз diogram2DF = ( newDF2.groupby ('Станция метрополитена', as_index=False) .agg ({'Входы пассажиров': 'sum', 'Выходы пассажиров': 'sum' }) )
делаем график точечная диаграмма по 2 значениям fig, ax = plt.subplots (figsize=(10, 10)) ax.scatter (diogram2DF['Входы пассажиров'], diogram2DF['Выходы пассажиров'], s=15, facecolor = colums) plt.xlabel ('Входы пассажиров в млн. год', color = text_color, fontname = fnt) plt.ylabel ('Выходы пассажиров в млн. год', color = text_color, fontname = fnt) plt.title ('Колличество входов и выходов пассажиров за 2025 год на Замоскворецкой линии по станциям', color = text_color, fontname = fnt) # название plt.grid (True, alpha = 0.2)
обозначаем пассажиров в миллионах ax.yaxis.set_major_formatter ( plt.FuncFormatter (lambda x, _: f'{x/1000000:.2f}') ) ax.xaxis.set_major_formatter ( plt.FuncFormatter (lambda x, _: f'{x/1000000:.2f}') )
подписи точек for i, row in diogram2DF.iterrows (): ax.annotate ( row['Станция метрополитена'], (row['Входы пассажиров'], row['Выходы пассажиров']), textcoords="offset points», xytext=(5, -2), fontsize=7 ) plt.show ()
берём значения только за один год newDF3 = df_PT[ (df_PT['Год'] == 2025) ]
удаляем закрытую линию newDF3 = newDF3[newDF3['Линия'] ≠ 'Каховская линия']
собираем датафрейм для визуализации, суммируем пассажиропоток на всех станциях по линиям diogram3DF = ( newDF3.groupby ('Линия', as_index=False)['Входы пассажиров'].sum () # уюираем повторы и суммируем )
делаем график круговая диаграмма, чтоыб понять на какую линию приходится больше всего входов fig, ax = plt.subplots (figsize=(8, 10)) ax.pie (diogram3DF['Входы пассажиров'], labels = diogram3DF['Линия'], autopct='%1.1f%%') plt.title ('Доля входов пассажиров за 2025 год по линиям', color = text_color, fontname = fnt) # название plt.grid (True, alpha = 0.2)
plt.show ()
newDF4 = df_PT
diogram4DF = ( df_PT.groupby (['Линия', 'Год'], as_index=False).agg ({'Входы пассажиров': 'sum'}) )
делаем график линейная диаграмма, чтоыб понять как менялось число входов на станции для удобства pivot_df = diogram4DF.pivot (index='Год', columns='Линия', values='Входы пассажиров')
Построение линейной диаграммы plt.figure (figsize=(12, 6)) for line in pivot_df.columns: plt.plot (pivot_df.index, pivot_df[line], marker='o', label=line)
plt.xlabel ('Год', color = text_color, fontname = fnt) plt.ylabel ('Входы пассажиров, млн', color = text_color, fontname = fnt) plt.title ('Динамика изменения числа входов пассажиров по линиям метро', color = text_color, fontname = fnt) plt.legend (title='Линия', bbox_to_anchor=(1.05, 1), loc='upper left') # легенда сбоку plt.grid (True, alpha = 0.2) plt.xticks (pivot_df.index) plt.tight_layout ()
переводим цифры в нормальный вид plt.gca ().yaxis.set_major_formatter ( plt.FuncFormatter (lambda x, _: f'{x/1000000:.0f}') )
plt.show ()
Визуализация
Эта диаграмма позволяет проанализировать число вошедших пассажиров на станции Арбатско-Покровской линии метро. Можно заметить что сильно выделяются станции Щелковская (крупный автовокзал), Славянский Бульвар (станция мцд, удобная пересадка для жителей Одинцова), Бауманская (большой кластер вузов).
Точечная диаграмма использовалась мною для поиска «аномальных» станций в метро. Такая нашлась на Замоскворецкой линии, люди выходят на Алма-Атинской, но обратно не заходят. Объяснения этому у меня найти не получилось.
Кроме того можно заметить станции которыми, казалось бы, никто и вовсе не пользуется. Но в действительности это особенность в датасета, часть пересадочных станций метро официально не имеют собственных выходов — только принадлежащие други линиям.
Круговая диаграмма была использована мной для иллюстрации доли каждой линии во общем числе входящих людей в метро. Можно заметить преобладание больших и старых радиальных линий.
Линейная диаграмма была использована для иллюстрации трендов числа входящих на станции метро. Большинство линий относительно стабильны во времени, но можно заметить рост входящих на строящихся новых линиях, например на Некрасовской. Кроме того хорошо заметен провал в числе входящих на Замоскворецкой линии в 2023 году, это связано с длительным закрытием участка линии на реконструкцию.
Список источников
[1] Пассажиропоток по станциям Московского метрополитена (URL: https://data.mos.ru/opendata/62743?version=1&release=32) (дата обращения 26.01.26)



