【竞赛系列】机器学习实操项目08——全球城市计算AI挑战赛(数据可视化分析)

发布于:2025-09-11 ⋅ 阅读:(19) ⋅ 点赞:(0)

上一章:【竞赛系列】机器学习实操项目07——全球城市计算AI挑战赛(baseline、时间序列分析、地铁流量预测)
下一章:
机器学习核心知识点目录:机器学习核心知识点目录
机器学习实战项目目录:【从 0 到 1 落地】机器学习实操项目目录:覆盖入门到进阶,大学生就业 / 竞赛必备

本文基于已有的地铁流量训练数据,进一步聚焦多站点、多日期的流量对比分析,通过时间特征提取与可视化,验证不同站点、不同日期的流量分布规律,为后续预测模型优化提供更细致的数据支撑。

通过网盘分享的文件:天池地铁流量预测
链接: https://pan.baidu.com/s/1k-sI1sDGufBSLJveNTm6nA?pwd=pgkk 提取码: pgkk

一、工具库导入与数据加载

1.1 导入数据分析与可视化工具库

该步骤加载数据处理(numpy/pandas)、特征工程(TF-IDF/SVD)、模型训练(XGBoost/LightGBM)及可视化(matplotlib/seaborn)所需库,部分库(如文本处理、机器学习模型)为备用,核心用于后续数据EDA的工具已标注,同时屏蔽警告确保输出简洁。

## 数据工具包(核心用于数值计算与表格数据处理)
import numpy as np
np.random.seed(42)  # 设置numpy随机种子,确保随机操作可复现
import pandas as pd  # 核心库,用于DataFrame构建、数据读写与清洗
from tqdm import tqdm  # 显示循环进度条,便于追踪数据处理进度

## 字符串处理工具包(本EDA案例暂未使用,备用)
import string  # 字符串操作(如标点处理)
import re  # 正则表达式,用于文本匹配与提取
import gensim  # 文本语义建模(如Word2Vec)
from collections import Counter  # 计数工具,用于统计元素频次
import pickle  # 数据序列化存储,便于保存中间结果
from nltk.corpus import stopwords  # NLTK停用词库,用于文本去噪

# 特征工程与模型评估工具(本EDA案例暂未使用机器学习模型,备用)
from sklearn.feature_extraction.text import TfidfVectorizer  # 文本TF-IDF特征提取
from sklearn.decomposition import TruncatedSVD  # 截断SVD,用于高维特征降维
from sklearn.preprocessing import StandardScaler  # 数据标准化,消除量纲影响
from sklearn.model_selection import train_test_split  # 划分训练集与测试集
from sklearn.metrics import roc_auc_score  # 计算AUC指标,评估分类模型
from sklearn.model_selection import KFold  # K折交叉验证,避免模型过拟合

import warnings
warnings.filterwarnings('ignore')  # 屏蔽运行过程中的警告信息,避免干扰输出

# 梯度提升树模型(本EDA案例暂未使用,备用)
import xgboost as xgb  # XGBoost模型,适用于结构化数据预测
import lightgbm as lgb  # LightGBM模型,高效处理大规模数据
from functools import partial  # 函数偏应用,用于固定部分函数参数

# 系统操作与时间处理工具(核心用于文件路径、内存管理与时间特征)
import os  # 系统文件操作,用于路径拼接、文件夹创建
import gc  # 垃圾回收,释放未使用的内存,避免内存溢出
from scipy.sparse import vstack  # 垂直堆叠稀疏矩阵(本案例暂未使用)
import time  # 时间管理,用于记录代码运行耗时
import datetime  # 日期时间处理,核心用于后续提取时间特征

import joblib  # 模型与特征保存工具(本案例暂未使用,备用)

# 多进程与可视化工具(核心用于并行处理与图表绘制)
import multiprocessing as mp  # 多进程处理,提升数据处理效率(本案例暂未使用)
import pandas as pd  # 重复导入,确保代码独立运行时无依赖问题
import numpy as np  # 重复导入,确保代码独立运行时无依赖问题
import matplotlib.pyplot as plt  # 核心可视化库,用于绘制折线图、柱状图等
import re  # 重复导入,确保代码独立运行时无依赖问题
%matplotlib inline  # 设置Jupyter Notebook中图像内嵌显示,无需额外调用plt.show()
import seaborn as sns  # 基于matplotlib的高级可视化库,美化图表样式
%matplotlib inline  # 重复设置,确保图像内嵌生效

1.2 读取地铁流量训练数据与测试提交模板

该步骤读取核心训练数据(df_data.csv)与测试提交模板(testA_submit_2019-01-29.csv),训练数据包含“站点ID、时间段、进站人数、出站人数”等关键信息,后续EDA将基于训练数据展开,测试模板用于后续预测结果填充(本部分暂未涉及)。

from tqdm import tqdm  # 重复导入,确保代码块独立运行
from tqdm import tqdm_notebook  # 显示Notebook环境下的进度条(本案例暂未使用)

# 读取地铁流量训练数据:包含314928条10分钟级记录,涵盖多个站点的进出站人数
df_data = pd.read_csv('./input/df_data.csv')
# 读取测试提交模板:需预测2019-01-29日各站点的10分钟级进出站人数,本部分暂用其结构
test_A_submit = pd.read_csv('./input/testA_submit_2019-01-29.csv') 

二、时间特征工程(提取精细化时间维度)

2.1 从时间戳提取多维度时间特征

该步骤将原始startTime(字符串格式)解析为datetime格式,进一步提取“日(day)、小时(hours_in_day)、星期几(day_of_week)、日内10分钟段(ten_minutes_in_day)”4个核心时间特征,为后续“按日期/小时/时段”的流量对比分析提供维度支持。

# 时间相关特征:将startTime(字符串)解析为datetime格式,便于提取细分时间特征
df_data['time'] = pd.to_datetime(df_data['startTime'])
# 提取“日”特征:1-31,对应月份中的具体日期(如1月1日为1,1月2日为2)
df_data['day'] = df_data['time'].dt.day  
# 提取“小时”特征:0-23,对应一天中的24个小时(如凌晨0点为0,中午12点为12)
df_data['hours_in_day'] = df_data['time'].dt.hour 
# 提取“星期几”特征:0-6,0代表星期一,6代表星期日(用于区分工作日/周末)
df_data['day_of_week'] = df_data['time'].dt.dayofweek 
# 提取“日内10分钟段”特征:0-143,一天24小时×6个10分钟段=144个段(如00:00-00:10为0,23:50-24:00为143)
df_data['ten_minutes_in_day'] = df_data['hours_in_day'] * 6 + df_data['time'].dt.minute // 10 
# 删除临时的time列(已提取所有所需时间特征,避免数据冗余)
del df_data['time']

三、多站点流量可视化分析(按日期对比)

3.1 1月1日0-9号站点进站人数对比

该步骤筛选1月1日(day==1)的数据,以“日内10分钟段”为x轴、“进站人数(inNums)”为y轴,绘制0-9号共10个站点的流量趋势图,核心目的是对比不同站点在同一日期的流量分布差异(如高峰时段、流量峰值大小)。

# 筛选1月1日(day==1)的所有站点数据
tmp = df_data[df_data.day==1]
# 生成x轴数据:日内10分钟段的索引(0-143),基于0号站点的时段数量构建,确保所有站点x轴一致
dt = [r for r in range(tmp.loc[tmp.stationID==0, 'ten_minutes_in_day'].shape[0])]

# 创建图像:设置画布大小为20×10(宽×高),便于清晰展示10条曲线
fig = plt.figure(1,figsize=[20,10])
# 设置y轴标签:进站人数(inNums)
plt.ylabel('inNums')
# 设置x轴标签:日期(此处特指1月1日,x轴实际为日内10分钟段)
plt.xlabel('date')
# 设置图表标题:1月1日0-9号站点进站人数对比
plt.title('inNums of stationID ')

# 循环绘制0-9号站点的进站人数趋势
for i in range(0,10):
    # 筛选当前站点(i)的1月1日数据,按10分钟段排序后取inNums,绘制折线
    plt.plot(dt, tmp.loc[tmp.stationID==i, 'inNums'], label = str(i)+' stationID' )

# 添加图例:区分不同站点的曲线,默认显示在右上角
plt.legend()
# 显示图像(因设置了%matplotlib inline,可省略,但保留确保兼容性)
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.2 1月1日0-9号站点出站人数对比

该步骤与3.1逻辑一致,仅将指标从“进站人数(inNums)”改为“出站人数(outNums)”,目的是对比同一日期(1月1日)不同站点的出站流量分布差异,观察进站与出站高峰是否错位(如早高峰进站集中,晚高峰出站集中)。

# 筛选1月1日(day==1)的所有站点数据
tmp = df_data[df_data.day==1]
# 生成x轴数据:日内10分钟段索引(0-143),与3.1保持一致
dt = [r for r in range(tmp.loc[tmp.stationID==0, 'ten_minutes_in_day'].shape[0])]

# 创建图像:画布大小20×10
fig = plt.figure(1,figsize=[20,10])
# 设置y轴标签:出站人数(outNums)
plt.ylabel('outNums')
# 设置x轴标签:日期(1月1日)
plt.xlabel('date')
# 设置图表标题:1月1日0-9号站点出站人数对比
plt.title('outNums of stationID ')

# 循环绘制0-9号站点的出站人数趋势
for i in range(0,10):
    plt.plot(dt, tmp.loc[tmp.stationID==i, 'outNums'], label = str(i)+' stationID' )

# 添加图例
plt.legend()
# 显示图像
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.3 1月3日0-9号站点出站人数对比

该步骤将日期改为1月3日(day==3),重复3.2的出站人数对比逻辑,目的是观察“同一批站点(0-9号)在不同日期的流量模式是否一致”——若曲线趋势相似(如高峰时段相同),则验证流量分布的稳定性,为后续预测提供规律支撑。

# 筛选1月3日(day==3)的所有站点数据
tmp = df_data[df_data.day==3]
# 生成x轴数据:日内10分钟段索引(0-143)
dt = [r for r in range(tmp.loc[tmp.stationID==0, 'ten_minutes_in_day'].shape[0])]

# 创建图像:画布大小20×10
fig = plt.figure(1,figsize=[20,10])
# 设置y轴标签:出站人数(outNums)
plt.ylabel('outNums')
# 设置x轴标签:日期(1月3日)
plt.xlabel('date')
# 设置图表标题:1月3日0-9号站点出站人数对比
plt.title('outNums of stationID ')

# 循环绘制0-9号站点的出站人数趋势
for i in range(0,10):
    plt.plot(dt, tmp.loc[tmp.stationID==i, 'outNums'], label = str(i)+' stationID' )

# 添加图例
plt.legend()
# 显示图像
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.4 1月1日及以后0-9号站点进站人数对比

该步骤筛选1月1日及以后(day>=1)的所有数据,绘制0-9号站点的进站人数趋势,目的是观察“多日期叠加下的流量整体规律”——若同一站点在不同日期的曲线高度重合,说明该站点流量模式稳定;若存在明显差异(如某日期流量骤降),则需排查是否为节假日或特殊事件。

# 筛选1月1日及以后(day>=1)的所有站点数据
tmp = df_data[df_data.day>=1]
# 生成x轴数据:日内10分钟段索引(0-143)
dt = [r for r in range(tmp.loc[tmp.stationID==0, 'ten_minutes_in_day'].shape[0])]

# 创建图像:画布大小20×10
fig = plt.figure(1,figsize=[20,10])
# 设置y轴标签:进站人数(inNums)
plt.ylabel('inNums')
# 设置x轴标签:日期(1月1日及以后)
plt.xlabel('date')
# 设置图表标题:1月1日及以后0-9号站点进站人数对比
plt.title('inNums of stationID ')

# 循环绘制0-9号站点的进站人数趋势
for i in range(0,10):
    plt.plot(dt, tmp.loc[tmp.stationID==i, 'inNums'], label = str(i)+' stationID' )

# 添加图例
plt.legend()
# 显示图像
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

四、单站点多日期流量对比(按小时聚合)

4.1 4号站点1月4日vs1月5日进站人数小时级对比

该步骤聚焦4号站点(高流量站点,前期分析中已关注),筛选1月4日和5日的数据,按“小时(hours_in_day)”聚合计算每小时平均进站人数,用带圆点的折线图(style='o-')对比两天的小时级流量差异,核心观察“相邻日期的小时级流量模式是否一致”(如早高峰是否都在7-9点)。

# 筛选4号站点1月4日和5日(day.isin([4,5]))的数据
tmp = df_data.loc[(df_data.day.isin([4,5]))]
# 按“小时(hours_in_day)”和“日期(day)”聚合,计算每小时进站人数均值
# 绘制对比图:x轴为小时(0-23),y轴为平均进站人数,不同日期用不同颜色曲线
tmp.loc[tmp.stationID == 4].pivot_table(index='hours_in_day',\
                                        columns='day',values='inNums').plot(style='o-')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.2 4号站点1月3日vs1月4日进站人数小时级对比

该步骤将日期改为1月3日和4日,重复4.1的逻辑,进一步验证4号站点“非连续相邻日期”的小时级流量稳定性——若3日和4日的高峰时段、流量峰值相近,说明该站点流量受日期连续性影响小,模式更稳定,预测时可参考更多历史日期。

# 筛选4号站点1月3日和4日(day.isin([3,4]))的数据
tmp = df_data.loc[(df_data.day.isin([3,4]))]
# 按“小时”和“日期”聚合,计算每小时进站人数均值并绘制对比图
tmp.loc[tmp.stationID == 4].pivot_table(index='hours_in_day',\
                                        columns='day',values='inNums').plot(style='o-')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.3 4号站点1月1-4日进站人数小时级对比

该步骤扩展日期范围至1月1-4日,按小时聚合4号站点的进站人数,绘制4条日期曲线,目的是观察“多日期叠加下的小时级流量规律”——若4条曲线趋势一致(如早高峰7-9点、晚高峰17-19点),则可确定该站点的核心流量模式,为预测时的“小时级比例映射”提供直接依据。

# 筛选4号站点1月1-4日(day.isin([1,2,3,4]))的数据
tmp = df_data.loc[(df_data.day.isin([1,2,3,4]))]
# 按“小时”和“日期”聚合,计算每小时进站人数均值并绘制对比图
tmp.loc[tmp.stationID == 4].pivot_table(index='hours_in_day',\
                                        columns='day',values='inNums').plot(style='o-')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.4 4号站点每日出站人数总量统计

该步骤按“日(day)”聚合4号站点的出站人数总量,输出1月1-29日(29日为预测日,数据为0)的统计结果,核心用于观察“每日流量总量的变化趋势”——如1月1日(元旦)流量较低,1月2-4日(工作日)流量回升且稳定,为预测时的“日期类型调整系数”(如节假日系数、工作日系数)提供数据支撑。

# 按“日(day)”聚合4号站点的出站人数总量,输出各日期的累计出站人数
df_data[df_data.stationID==4].groupby(['day'])['outNums'].sum()

输出结果:

day
1     24016.0
2     38615.0
3     38065.0
4     38791.0
5     25276.0
6     21186.0
7     37678.0
8     37507.0
9     36826.0
10    37480.0
11    38778.0
12    25621.0
13    22081.0
14    38860.0
15    37295.0
16    38719.0
17    39327.0
18    41707.0
19    27112.0
20    23881.0
21    40142.0
22    39285.0
23    39348.0
24    39737.0
25    39597.0
28    36844.0
29        0.0
Name: outNums, dtype: float64

4.5 查看处理后的数据全貌

该步骤展示经过时间特征工程处理后的完整数据集df_data,包含原始字段(站点ID、时间段、进出站人数)和新增时间特征(日、小时、星期几、日内10分钟段),便于直观了解数据结构与字段含义,确认特征提取结果是否符合预期,为后续更复杂的分析或建模提供数据基础。

df_data

输出结果:

stationID startTime endTime inNums outNums day hours_in_day day_of_week ten_minutes_in_day
0 0 2019-01-01 00:00:00 2019-01-01 00:10:00 0.0 0.0 1 0 1 0
1 0 2019-01-01 00:10:00 2019-01-01 00:20:00 0.0 0.0 1 0 1 1
2 0 2019-01-01 00:20:00 2019-01-01 00:30:00 0.0 0.0 1 0 1 2
3 0 2019-01-01 00:30:00 2019-01-01 00:40:00 0.0 0.0 1 0 1 3
4 0 2019-01-01 00:40:00 2019-01-01 00:50:00 0.0 0.0 1 0 1 4
... ... ... ... ... ... ... ... ... ...
314923 9 2019-01-29 23:10:00 2019-01-29 23:20:00 0.0 0.0 29 23 1 139
314924 9 2019-01-29 23:20:00 2019-01-29 23:30:00 0.0 0.0 29 23 1 140
314925 9 2019-01-29 23:30:00 2019-01-29 23:40:00 0.0 0.0 29 23 1 141
314926 9 2019-01-29 23:40:00 2019-01-29 23:50:00 0.0 0.0 29 23 1 142
314927 9 2019-01-29 23:50:00 2019-01-30 00:00:00 0.0 0.0 29 23 1 143

314928 rows × 9 columns

通过上述步骤,我们完成了从数据加载、时间特征提取到多维度可视化分析的全流程。核心发现包括:

  1. 不同站点在同一日期的流量分布存在显著差异(如峰值大小和时段);
  2. 同一站点在不同日期的流量模式具有稳定性(如高峰时段固定);
  3. 部分日期(如节假日)的流量总量与工作日存在明显差异。

这些规律为后续构建基于“时间序列相似性”的预测模型提供了关键依据。

上一章:【竞赛系列】机器学习实操项目07——全球城市计算AI挑战赛(baseline、时间序列分析、地铁流量预测)
下一章:
机器学习核心知识点目录:机器学习核心知识点目录
机器学习实战项目目录:【从 0 到 1 落地】机器学习实操项目目录:覆盖入门到进阶,大学生就业 / 竞赛必备


网站公告

今日签到

点亮在社区的每一天
去签到