基于地铁刷卡数据分析与可视化——以杭州市为例(二)
上篇文章提到,由于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名站点
文章仅用于分享个人学习成果与个人存档之用,分享知识,如有侵权,请联系作者进行删除。所有信息均基于作者的个人理解和经验,不代表任何官方立场或权威解读。