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

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

完整代码#运行环境Python 3.11

python 复制代码
# -*- 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

python 复制代码
# -*- 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

python 复制代码
# -*- 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名站点

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

相关推荐
SiYuanFeng30 分钟前
【问题未解决-寻求帮助】VS Code 中使用 Conda 环境,运行 Python 后 PowerShell 终端输出内容立即消失
开发语言·python·conda
智海观潮41 分钟前
DeepSeek在大数据领域正掀起一场深刻的变革
大数据·ai·deepseek
我是ed.1 小时前
cocos Js 使用 webview 通过 postMessage 进行通信
开发语言·javascript·ecmascript
段ヤシ.1 小时前
Windows环境下安装Python和PyCharm
开发语言·python·pycharm
大萌神Nagato1 小时前
如何修改VM虚拟机中的ip
linux·开发语言·ip·虚拟机·静态ip
陈煜的博客1 小时前
elasticSearch 增删改查 java api
java·大数据·elasticsearch
hweiyu001 小时前
Scala实用编程(附电子书资料)
开发语言·后端·scala
mftang1 小时前
C 标准库 <time.h> 函数详解
c语言·开发语言
lly2024061 小时前
SVG 在线编辑器
开发语言
脑袋大大的2 小时前
uni-app x开发避坑指南:拯救被卡顿的UI线程!
开发语言·前端·javascript·vue.js·ui·uni-app·uts