基于地铁刷卡数据分析与可视化——以杭州市为例(二)

上篇文章提到,由于2019年1月1日正好是元旦,为了消除节假日对数据分析的影响,我们选择了节后的一周来进行详细的客流分析。具体日期选择为2019年1月8日至1月14日。在这段时间内,我们关注的是地铁线路的进站客流情况。数据表中的 'status' 字段表示进出站状态,其中0代表出站,1代表进站。我们的目标是计算这一周内三条地铁线路(A线、B线和C线)的平均进站客流量,以全面了解各线路的客流分布和高峰时段的特点;

完整代码#运行环境Python 3.11

# -*- coding: utf-8 -*-

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

# 文件路径列表
file_paths = [
    'D:\\data\\record_2019-01-08.csv',
    'D:\\data\\record_2019-01-09.csv',
    'D:\\data\\record_2019-01-10.csv',
    'D:\\data\\record_2019-01-11.csv',
    'D:\\data\\record_2019-01-12.csv',
    'D:\\data\\record_2019-01-13.csv',
    'D:\\data\\record_2019-01-14.csv'
]

# 存储每个日期的每小时客流量
daily_hourly_counts = []

# 读取每个CSV文件并计算每小时客流量
for file_path in file_paths:
    df = pd.read_csv(file_path)

    # 确保 'time' 列是 datetime 类型
    df['time'] = pd.to_datetime(df['time'])

    # 筛选条件:'lineID' = 'A' 且 'status' = 1
    filtered_df = df[(df['lineID'] == 'A') & (df['status'] == 1)]

    # 按 'time' 和 'stationID' 分组,并按小时汇总客流量
    hourly_station_customer_count = filtered_df.groupby([filtered_df['time'].dt.hour, 'stationID']).size().unstack(fill_value=0)

    # 将结果存储到列表中
    daily_hourly_counts.append(hourly_station_customer_count)

# 合并所有日期的每小时客流量
combined_hourly_counts = pd.concat(daily_hourly_counts, axis=0)

# 计算每个小时各个 stationID 的平均客流量
average_hourly_station_customer_count = combined_hourly_counts.groupby(combined_hourly_counts.index).mean()

# 打印结果
print("每个小时各个 'stationID' 的平均客流量:")
print(average_hourly_station_customer_count)

# 可视化
plt.figure(figsize=(14, 7))

# 为每个 stationID 绘制折线图
for station in average_hourly_station_customer_count.columns:
    plt.plot(average_hourly_station_customer_count.index, average_hourly_station_customer_count[station], label=f'Station {station}')

# 设置图表标题和标签
plt.title('每个小时各个 stationID 的平均客流量')
plt.xlabel('小时')
plt.ylabel('平均客流量')
plt.legend()
plt.grid(True)

# 显示图表
plt.show()

我们通过编写Python脚本来计算全天24小时内各个站点的进站客流量变化情况,并进一步对一周内的客流量数据求均值,以全面了解各站点的客流量分布特点;

A线路各个站点在全天的平均进站客流量分布情况

B线路各个站点在全天的平均进站客流量分布情况

C线路各个站点在全天的平均进站客流量分布情况

我们把数据的研究尺度进一步缩小,同样的,我们通过python脚本来计算一下,全天24小时的各个站点进站客流的早晚高峰峰值区间分布情况,并对一周的客流量求均值,我们来看各线路早晚高峰的15分钟峰值客流分布情况;

完整代码#运行环境Python 3.11

# -*- coding: utf-8 -*-

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号


def read_and_process_file(file_path):
    try:
        df = pd.read_csv(file_path)
        df['time'] = pd.to_datetime(df['time'])
        filtered_df = df[(df['lineID'] == 'A') & (df['status'] == 1)]
        # 按15分钟分组
        fifteen_minute_station_customer_count = filtered_df.groupby(
            [pd.Grouper(key='time', freq='15min'), 'stationID']).size().unstack(fill_value=0)
        return fifteen_minute_station_customer_count
    except Exception as e:
        print(f"Error processing file {file_path}: {e}")
        return None


# 文件路径列表
file_paths = [
    'D:\\data\\record_2019-01-08.csv',
    'D:\\data\\record_2019-01-09.csv',
    'D:\\data\\record_2019-01-10.csv',
    'D:\\data\\record_2019-01-11.csv',
    'D:\\data\\record_2019-01-12.csv',
    'D:\\data\\record_2019-01-13.csv',
    'D:\\data\\record_2019-01-14.csv'
]

# 存储每个日期的每15分钟客流量
daily_fifteen_minute_counts = []

# 读取每个CSV文件并计算每15分钟客流量
for file_path in file_paths:
    fifteen_minute_station_customer_count = read_and_process_file(file_path)
    if fifteen_minute_station_customer_count is not None:
        daily_fifteen_minute_counts.append(fifteen_minute_station_customer_count)

# 合并所有日期的每15分钟客流量
combined_fifteen_minute_counts = pd.concat(daily_fifteen_minute_counts, axis=0)

# 计算每15分钟各个 stationID 的平均客流量
average_fifteen_minute_station_customer_count = combined_fifteen_minute_counts.groupby(
    combined_fifteen_minute_counts.index.time).mean()

# 将索引转换为 DatetimeIndex
average_fifteen_minute_station_customer_count.index = pd.to_datetime(
    average_fifteen_minute_station_customer_count.index, format='%H:%M:%S')

# 打印结果
print("每15分钟各个 'stationID' 的平均客流量:")
print(average_fifteen_minute_station_customer_count)

# 确定早高峰和晚高峰15分钟区间
peak_intervals = {}
for station in average_fifteen_minute_station_customer_count.columns:
    # 早高峰时间段
    morning_peak = average_fifteen_minute_station_customer_count.between_time('06:00', '10:00')[station].idxmax()
    # 晚高峰时间段
    evening_peak = average_fifteen_minute_station_customer_count.between_time('16:00', '20:00')[station].idxmax()

    formatted_morning_peak = f"{morning_peak.strftime('%H:%M')}-{(morning_peak + pd.Timedelta(minutes=15)).strftime('%H:%M')}"
    formatted_evening_peak = f"{evening_peak.strftime('%H:%M')}-{(evening_peak + pd.Timedelta(minutes=15)).strftime('%H:%M')}"

    peak_intervals[station] = {
        'morning': formatted_morning_peak,
        'evening': formatted_evening_peak
    }

# 输出每个站点的早高峰和晚高峰15分钟区间
print("\n各站点早高峰和晚高峰进站客流的15分钟区间:")
for station, intervals in peak_intervals.items():
    print(f"Station {station}: 早高峰 {intervals['morning']}, 晚高峰 {intervals['evening']}")

# 可视化
fig, ax = plt.subplots(figsize=(14, 8))

# 为每个 stationID 绘制24小时刻度图
cmap = plt.get_cmap('tab10')  # 获取颜色映射
colors = [cmap(i % cmap.N) for i in range(len(peak_intervals))]

for i, (station, intervals) in enumerate(peak_intervals.items()):
    # 早高峰
    start_time, end_time = intervals['morning'].split('-')
    start_hour = int(start_time[:2]) + int(start_time[3:]) / 60
    end_hour = int(end_time[:2]) + int(end_time[3:]) / 60
    ax.axvspan(start_hour, end_hour, alpha=0.3, color=colors[i],
               label=f'Station {station} 早高峰 {intervals["morning"]}')

    # 晚高峰
    start_time, end_time = intervals['evening'].split('-')
    start_hour = int(start_time[:2]) + int(start_time[3:]) / 60
    end_hour = int(end_time[:2]) + int(end_time[3:]) / 60
    ax.axvspan(start_hour, end_hour, alpha=0.3, color=colors[i],
               label=f'Station {station} 晚高峰 {intervals["evening"]}')

# 设置图表标题和标签
ax.set_title('各站点早高峰和晚高峰进站客流的15分钟区间')
ax.set_xlabel('时间 (小时)')
ax.set_ylabel('客流量')
ax.set_xlim(0, 24)
ax.set_xticks(range(25))
ax.set_xticklabels([f'{i}:00' if i % 2 == 0 else '' for i in range(25)])

# 调整图例的位置和大小
ax.legend(loc='upper left', bbox_to_anchor=(1.05, 1), borderaxespad=0., fontsize='small')

# 手动调整子图之间的间距
plt.subplots_adjust(left=0.1, right=0.8, top=0.9, bottom=0.1)

# 显示图表
plt.show()

整体来说,这些线路的早高峰时间段: 大多数站点的早高峰集中在08:00-08:30之间,特别是08:00-08:15和08:15-08:30两个时间段。 个别站点的早高峰时间较晚,如Station 76(09:45-10:00)和Station 77(09:30-09:45);我们可以看到,晚高峰的分布时刻带更宽,根据站点的分布情况和地理位置等情况,个站点晚高峰到来的时刻更早或晚,大多数站点的晚高峰集中在17:15-18:00之间,特别是17:15-17:30和17:30-17:45两个时间段;

A线路各个站点在全天的进站客流量中,早晚高峰15分钟的最大客流时刻分布情况

B线路各个站点在全天的进站客流量中,早晚高峰15分钟的最大客流时刻分布情况

C线路各个站点在全天的进站客流量中,早晚高峰15分钟的最大客流时刻分布情况

我们使用Python脚本再来探究一下地铁各线路的进站客流数据进行分析,找出各线路进站客流前10名的站点客流分布情况和特征;

完整代码#运行环境Python 3.11

# -*- coding: utf-8 -*-

import pandas as pd

def read_and_process_file(file_path):
    try:
        df = pd.read_csv(file_path)
        df['time'] = pd.to_datetime(df['time'])
        return df
    except Exception as e:
        print(f"Error processing file {file_path}: {e}")
        return None

# 文件路径列表
file_paths = [
    'D:\\data\\record_2019-01-08.csv',
    'D:\\data\\record_2019-01-09.csv',
    'D:\\data\\record_2019-01-10.csv',
    'D:\\data\\record_2019-01-11.csv',
    'D:\\data\\record_2019-01-12.csv',
    'D:\\data\\record_2019-01-13.csv',
    'D:\\data\\record_2019-01-14.csv'
]

# 读取并处理所有文件
dfs = [read_and_process_file(file_path) for file_path in file_paths]
df = pd.concat(dfs, ignore_index=True)

# 过滤 A 线的数据
a_line_data = df[df['lineID'] == 'A']

# 提取进站数据
inbound_data = a_line_data[a_line_data['status'] == 1]

# 计算每天的平均进站客流
daily_inbound_flow = inbound_data.groupby([inbound_data['time'].dt.date, 'stationID'])['userID'].count().reset_index()
daily_inbound_flow.columns = ['date', 'stationID', 'inbound_count']

# 计算每个站点的平均进站客流
average_inbound_flow = daily_inbound_flow.groupby('stationID')['inbound_count'].mean().reset_index()
average_inbound_flow.columns = ['stationID', 'average_inbound_count']

# 按平均进站客流排序并取前10名
top_10_inbound_stations = average_inbound_flow.sort_values(by='average_inbound_count', ascending=False).head(10)

# 输出前10名站点的平均进站客流到 CSV 文件
output_file_path = 'D:\\data\\top_10_inbound_stations.csv'
top_10_inbound_stations.to_csv(output_file_path, index=False)
print(f"Top 10 inbound stations data saved to {output_file_path}")

我们可以看到A线路每天平均进站客流前10名站点客流呈阶梯式递减,B线路每天平均进站客流前10名站点中编码15的站点客流占大头,其他客流呈较为相似状态,差别不大,C线路每天平均进站客流前10名站点中,客流客流较为均衡,线路整体各站点进站客流较为平稳;

A线路每天平均进站客流前10名站点

B线路每天平均进站客流前10名站点

C线路每天平均进站客流前10名站点

文章仅用于分享个人学习成果与个人存档之用,分享知识,如有侵权,请联系作者进行删除。所有信息均基于作者的个人理解和经验,不代表任何官方立场或权威解读。

【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于Python编写的中国城市轨道交通数据可视化分析项目源码+项目说明.zip ## 概述 > - 本项目是一个基于 Python 的简单数据可视化分析的小Demo。通过这个项目可以练习使用Python数据可视化分析相关的强大的库和模块,练习绘制简单的GUI界面并且连接数据库,更加深了对Python语言的学习和拓展。本项目也可作为学校的大作业、大实验实践或者课程设计等的选题项目。 > - 本项目通过多线程爬虫获取了高德地图中的中国轨道交通的一些数据信息,高德地图这个权威的网站也保证了数据的完整可靠性,然后进行了一些简单并且有趣的数据可视化分析,另外还设计了一个GUI界面,查询数据库或者文件中的一些信息。 > > - 如发现文档中或者源代码中有错误,欢迎大家在 `Issues` 中研究讨论,欢迎大家 `Fork` 和 `Pull requests` 改善代码,十分感谢! ## 使用语言 - Python 3 ## 主要技术 * **网络编程** * **多线程** * **文件操作** * **数据库编程** * **GUI** * **数据分析** ## 导入的库和模块 ```python import json import requests from bs4 import BeautifulSoup import sqlite3 import threading import tkinter as tk from tkinter import scrolledtext import pandas as pd from pyecharts import Line, Bar, Geo import numpy as np from wordcloud import WordCloud, ImageColorGenerator import jieba import matplotlib.pyplot as plt import seaborn as sns ``` ## 项目整体思路 1. 网页分析 2. 多线程爬虫爬取信息 3. 数据保存至文件中和数据库中 4. 利用 tkinter 绘制 GUI 界面,实现查询线路和站点两个功能 5. 数据可视化分析 (1)直接控制台显示分析结果 (2)绘制中国地图、柱状图等,生成 .html 文件 (3)绘制词云 (4)绘制柱状图、饼状图、折线图、散点图、双变量图等,生成 .png 文件 ## 运行 - 分别运行`src`文件夹中的`.py`文件即可 ## 部分运行结果样 .....
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图说交通

买猫粮,楼下的流浪猫在等我

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值