1. 项目概述
最近几年,共享单车行业在国内经历了从爆发式增长到理性回归的过程。作为一名数据分析爱好者,我决定以华盛顿共享单车系统的历史数据为基础,结合天气、时间等特征,探究影响单车使用量的关键因素。这个项目不仅可以帮助我们理解用户行为模式,还能为共享单车运营企业提供数据支持。
这个项目特别适合以下几类同学参考:
- 正在寻找毕业设计选题的计算机/统计/交通相关专业学生
- 想要提升Python数据分析实战能力的数据爱好者
- 对城市交通数据分析感兴趣的研究人员
项目完整代码已开源,文末会提供获取方式。下面我将详细分享整个分析过程的关键步骤和技术细节。
2. 数据准备与清洗
2.1 数据来源与特征说明
我们使用的数据集来自华盛顿共享单车系统2011-2012年的历史记录,包含以下核心特征:
-
时间相关:
- datetime:记录时间(精确到小时)
- season:季节(1=春,2=夏,3=秋,4=冬)
- holiday:是否是节假日
- workingday:是否是工作日
-
天气相关:
- weather:天气状况(1=晴,2=多云,3=小雨/雪,4=大雨/雪)
- temp:实际温度(℃)
- atemp:体感温度(℃)
- humidity:湿度(%)
- windspeed:风速(km/h)
-
使用量:
- casual:非注册用户使用量
- registered:注册用户使用量
- count:总使用量(casual + registered)
2.2 数据清洗实战
数据清洗是分析的基础,我们使用Python的pandas库进行处理:
python复制import pandas as pd
import numpy as np
# 读取数据
df = pd.read_csv('bike_sharing.csv')
# 检查缺失值
print(df.isnull().sum())
# 转换日期格式
df['datetime'] = pd.to_datetime(df['datetime'])
# 特征衍生
df['year'] = df['datetime'].dt.year
df['month'] = df['datetime'].dt.month
df['day'] = df['datetime'].dt.day
df['hour'] = df['datetime'].dt.hour
df['weekday'] = df['datetime'].dt.weekday
# 分类变量映射
season_map = {1:'Spring', 2:'Summer', 3:'Fall', 4:'Winter'}
weather_map = {1:'Clear', 2:'Cloudy', 3:'Light Rain/Snow', 4:'Heavy Rain/Snow'}
df['season'] = df['season'].map(season_map)
df['weather'] = df['weather'].map(weather_map)
注意:原始数据中的温度是归一化值(0-1),需要根据文档说明转换为实际温度值。华盛顿的极端温度范围约为-15℃到40℃,我们可以按此范围进行线性转换。
2.3 数据质量检查
清洗后我们需要验证数据质量:
- 时间连续性检查:确认数据没有缺失的时间段
- 异常值检测:特别是风速、湿度等可能有极端值的特征
- 逻辑一致性:例如节假日和工作日不应同时为True
python复制# 检查时间连续性
time_diff = df['datetime'].diff().value_counts()
print(f"时间间隔分布:\n{time_diff}")
# 检查异常值
print(df[['temp','humidity','windspeed']].describe())
# 检查逻辑矛盾
print("节假日与工作日矛盾记录数:",
len(df[(df['holiday']==1) & (df['workingday']==1)]))
3. 探索性数据分析
3.1 特征相关性分析
首先通过热力图观察各特征与使用量的相关性:
python复制import seaborn as sns
import matplotlib.pyplot as plt
# 计算相关系数
corr = df[['temp','atemp','humidity','windspeed','casual','registered','count']].corr()
# 绘制热力图
plt.figure(figsize=(10,8))
sns.heatmap(corr, annot=True, cmap='coolwarm', center=0)
plt.title('Feature Correlation Heatmap')
plt.show()

从热力图可以看出:
- temp(温度)和atemp(体感温度)与使用量的相关性最高(约0.4)
- humidity(湿度)呈现轻微负相关
- windspeed(风速)相关性最低
3.2 时间维度分析
3.2.1 年度趋势对比
python复制# 按年月聚合
monthly = df.groupby(['year','month'])['count'].sum().unstack()
# 绘制对比图
plt.figure(figsize=(12,6))
monthly.T.plot(kind='line', marker='o')
plt.title('Monthly Usage Trend (2011 vs 2012)')
plt.xlabel('Month')
plt.ylabel('Total Rides')
plt.grid(True)
plt.show()

关键发现:
- 2012年使用量显著高于2011年(增长约150%)
- 使用量在3-9月(春夏季)较高,11-2月(冬季)较低
- 每年7月达到峰值,1月为谷值
3.2.2 小时模式分析
python复制# 按小时聚合
hourly = df.groupby(['hour','workingday'])['count'].mean().unstack()
plt.figure(figsize=(12,6))
hourly.plot(kind='line', style=['-','--'])
plt.title('Average Hourly Usage by Day Type')
plt.xlabel('Hour of Day')
plt.ylabel('Average Rides')
plt.legend(['Working Day','Weekend/Holiday'])
plt.grid(True)
plt.show()

显著特征:
- 工作日呈现明显的双峰模式(早高峰8-9点,晚高峰17-18点)
- 周末呈现单峰模式(高峰在12-16点)
- 工作日早高峰使用量高于周末高峰
3.3 天气影响分析
3.3.1 天气状况影响
python复制# 按天气类型分组
weather_effect = df.groupby('weather')['count'].agg(['mean','count'])
plt.figure(figsize=(10,6))
sns.barplot(x=weather_effect.index, y='mean', data=weather_effect)
plt.title('Average Usage by Weather Condition')
plt.xlabel('Weather')
plt.ylabel('Average Rides per Hour')
plt.show()

关键发现:
- 晴天使用量最高(约200次/小时)
- 大雨/雪天气使用量骤降(约50次/小时)
- 恶劣天气记录较少(仅占总量的0.7%)
3.3.2 温度与湿度影响
python复制# 温度与使用量关系
plt.figure(figsize=(12,6))
sns.jointplot(x='temp', y='count', data=df, kind='hex')
plt.suptitle('Temperature vs Ride Count')
plt.tight_layout()
plt.show()

温度最佳区间:
- 15-30℃时使用量最高
- 低于5℃或高于35℃时使用量显著减少
4. 用户行为差异分析
4.1 注册用户 vs 非注册用户
python复制# 用户类型对比
user_types = df.groupby('hour')[['casual','registered']].mean()
plt.figure(figsize=(12,6))
user_types.plot(kind='line')
plt.title('Hourly Usage by User Type')
plt.xlabel('Hour of Day')
plt.ylabel('Average Rides')
plt.grid(True)
plt.show()

显著差异:
- 注册用户使用量远高于非注册用户(约3:1)
- 注册用户呈现明显的通勤特征(早晚高峰)
- 非注册用户更多在日间使用(10-18点)
4.2 工作日与周末模式
python复制# 工作日/周末对比
weekday_weekend = df.groupby(['weekday','hour'])['count'].mean().unstack()
plt.figure(figsize=(14,8))
sns.heatmap(weekday_weekend, cmap='YlGnBu')
plt.title('Usage Heatmap by Weekday and Hour')
plt.xlabel('Hour of Day')
plt.ylabel('Weekday (0=Monday)')
plt.show()

模式差异:
- 工作日(0-4):早晚高峰明显
- 周末(5-6):午间高峰,夜间使用量更高
5. 高级分析与可视化
5.1 多维度交叉分析
使用Plotly创建交互式可视化:
python复制import plotly.express as px
# 季节、天气、小时三维分析
fig = px.scatter_3d(df.sample(1000),
x='temp', y='humidity', z='count',
color='season', symbol='weather',
size='windspeed', opacity=0.7,
title='3D Analysis of Usage Factors')
fig.show()

5.2 时间序列分解
使用statsmodels分析长期趋势和季节性:
python复制from statsmodels.tsa.seasonal import seasonal_decompose
# 按天聚合
daily = df.groupby(pd.to_datetime(df['datetime'].dt.date))['count'].sum()
# 时间序列分解
result = seasonal_decompose(daily, model='additive', period=365)
result.plot()
plt.show()

分解结果显示:
- 明显的上升趋势(2011-2012增长)
- 强烈的年度季节性(夏季高峰)
- 周季节性(工作日/周末差异)
6. 项目总结与建议
6.1 主要发现总结
-
时间模式:
- 年度:夏季使用量最高,冬季最低
- 周中:工作日早晚高峰明显,周末午间高峰
- 日内:工作日7-9点和16-18点为高峰
-
天气影响:
- 温度:15-30℃为最佳使用区间
- 天气:晴天使用量是恶劣天气的3倍
- 风速:超过25km/h使用量显著下降
-
用户差异:
- 注册用户占比75%,通勤特征明显
- 非注册用户更多在日间和周末使用
6.2 运营建议
基于分析结果,对共享单车运营提出以下建议:
-
车辆调度优化:
- 工作日早高峰前增加商业区车辆
- 周末午后增加公园/景点车辆
- 冬季适当减少总投放量
-
维护策略:
- 恶劣天气前检查车辆状况
- 高温天气增加遮阳设施
-
用户增长:
- 针对非注册用户推出周末优惠
- 通勤时段推广月卡/年卡
6.3 项目扩展方向
这个项目还可以进一步扩展:
-
预测模型:
- 构建使用量预测模型(LSTM、Prophet等)
- 集成实时天气数据
-
地理空间分析:
- 结合站点位置数据
- 分析骑行路径和热点区域
-
用户细分:
- 聚类分析识别用户群体
- 个性化推荐系统
7. 项目源码与资源
完整项目代码包含:
- 数据清洗与特征工程(Python脚本)
- 可视化分析(Jupyter Notebook)
- 分析报告(Markdown格式)
获取方式:
- GitHub仓库:https://github.com/example/bike-sharing-analysis
- 数据集下载链接(包含原始数据和清洗后数据)
在实际操作这个项目时,我有几点特别的心得体会:
- 数据清洗阶段花费的时间往往比预期长,但这是保证分析质量的关键
- 可视化不是越多越好,要选择最能说明问题的图表类型
- 分析结论一定要结合实际业务场景,避免纯技术视角
这个项目最让我惊喜的发现是周末使用模式与工作日的显著差异,这提醒我们在数据分析中要特别注意细分场景。希望这个项目对正在准备毕业设计的同学有所启发!