当前位置: 首页 > news >正文

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

上篇文章提到,由于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' = 1filtered_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_countexcept 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:]) / 60end_hour = int(end_time[:2]) + int(end_time[3:]) / 60ax.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:]) / 60end_hour = int(end_time[:2]) + int(end_time[3:]) / 60ax.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 pddef read_and_process_file(file_path):try:df = pd.read_csv(file_path)df['time'] = pd.to_datetime(df['time'])return dfexcept 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名站点

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


http://www.mrgr.cn/news/68759.html

相关文章:

  • 计算机网络——SDN
  • 中小跨境卖家如何选择物流?
  • 【LeetCode】【算法】300. 最长递增子序列
  • MinGW-w64_10.0.0 + GCC12_x86_64-12.2.0-release-posix-seh-msvcrt-rt_v10-rev2.zip
  • vue中html如何转成pdf下载,pdf转base64,忽略某个元素渲染在pdf中,方法封装
  • mysql特性
  • 2.索引:深入解析 B+ 树:原理、MySQL 应用及与其他数据结构的对比
  • 在实际的网络通信中,客户端发起请求的常见流程
  • Java多线程(锁的操作)
  • IO作业day4
  • 发布一个npm组件库包
  • 哈哈,这可是“加长版”吐槽,我先声明,绝对有趣但绝对善意的深度吐槽!你要是真的看完
  • 算法训练(leetcode)二刷第二十天 | 93. 复原 IP 地址、78. 子集、90. 子集 II
  • 标准遗传算法-c++源程序
  • 从0开始学习机器学习--Day19--学习曲线
  • Moment.js、Day.js、Miment,日期时间库怎么选?
  • leetcode hot100【LeetCode 17.电话号码的字母组合】java实现
  • 快速开发工具 Vite
  • 大模型微调技术 --> IA3
  • LeetCode 每日一题 长度为 K 的子数组的能量值
  • 牛客小白月赛104-D小红开锁-模拟
  • c++:stack,queue,priority_queue模拟实现
  • 软件设计师中级 第9章 数据库技术基础
  • 从零开始学习python 7(持续更新ing)
  • 有趣的Midjourney作品赏析(附提示词)
  • Leetcode 长度最小的子数组