1. 项目概述
这个共享单车数据分析项目源于我在完成毕业设计时的实际需求。当时我发现,虽然共享单车已经深入城市生活的方方面面,但关于其使用规律的量化研究却相对匮乏。于是,我决定利用2017年5月北京地区的共享单车订单数据,通过Python数据分析技术,揭示用户使用行为的时空特征。
这个项目特别适合以下几类读者:
- 正在寻找数据分析项目灵感的学生
- 希望了解共享单车运营规律的从业者
- 对城市交通数据分析感兴趣的开发者
- 需要完成类似毕业设计的同学
2. 数据准备与预处理
2.1 数据来源与结构
原始数据来自2017年5月10日至24日北京地区的共享单车订单记录,包含以下关键字段:
- 用户ID(userid)
- 订单ID(orderid)
- 开始时间(starttime)
- 结束时间(endtime)
- 起始位置(geohashed_start_loc)
- 结束位置(geohashed_end_loc)
数据量较大,完整记录超过100万条。为便于分析,我首先对数据进行抽样处理,提取了连续7天(5月10-16日)数据的1%作为分析样本。
2.2 数据清洗与转换
数据预处理是分析的关键环节,我主要进行了以下处理:
python复制import pandas as pd
import geohash as gh
from geopy import distance
# 读取数据
df = pd.read_csv("train.csv", encoding="gbk")
# 时间处理
df['startdate'] = df['starttime'].str.split(' ').str[0]
df['hour'] = df['starttime'].str.split(' ').str[1].str[:2]
# 地理编码转换
def decode_geohash(geohash):
try:
return gh.decode(geohash)
except:
return (None, None)
df['start_latlon'] = df['geohashed_start_loc'].apply(decode_geohash)
df['end_latlon'] = df['geohashed_end_loc'].apply(decode_geohash)
# 计算骑行距离
def calc_distance(row):
try:
return distance.distance(row['start_latlon'], row['end_latlon']).km
except:
return 0
df['distance'] = df.apply(calc_distance, axis=1)
注意:geohash编码精度会影响距离计算的准确性。当编码长度为7位时,850米以内的距离难以精确区分,这部分数据在分析时需要特别处理。
3. 时间维度分析
3.1 日使用量对比
通过对7天数据的统计分析,我发现工作日和周末的使用模式存在显著差异:
- 工作日平均使用量占比54.23%
- 周末平均使用量占比45.77%
- 使用量整体呈稳步增长趋势
python复制# 按日期分组统计
daily_counts = df.groupby('startdate')['orderid'].count()
# 工作日与周末对比
workdays = ['2017-05-10','2017-05-11','2017-05-12','2017-05-15','2017-05-16']
weekends = ['2017-05-13','2017-05-14']
workday_avg = daily_counts[workdays].mean()
weekend_avg = daily_counts[weekends].mean()
3.2 小时级使用模式
更深入的小时级分析揭示了更有价值的规律:
工作日特征:
- 早高峰:7-9点
- 午间小高峰:11-13点
- 晚高峰:17-19点
- 通勤特征明显
周末特征:
- 使用量分布平缓:8-21点
- 午晚小高峰:11-12点和17-19点
- 休闲出行特征明显
python复制# 小时级使用量统计
hourly_counts = df.groupby(['startdate','hour'])['orderid'].count().unstack()
# 可视化代码示例
import matplotlib.pyplot as plt
plt.figure(figsize=(12,6))
for day in workdays[:3]:
plt.plot(hourly_counts.loc[day], label=day)
plt.title('Workday Usage Pattern')
plt.legend()
plt.show()
实操心得:时间分析时要注意时区问题。原始数据中的时间戳是UTC+8时区,如果数据来自不同地区,必须统一时区处理。
4. 空间维度分析
4.1 骑行距离分布
骑行距离分析揭示了共享单车的主要服务半径:
- 小于1公里:占比52.3%
- 1-2公里:占比34.7%
- 2-3公里:占比9.5%
- 大于3公里:占比3.5%
这一分布验证了共享单车作为"最后一公里"解决方案的定位。
python复制# 距离分组统计
bins = [0,1,2,3,10]
labels = ['<1km','1-2km','2-3km','>3km']
df['distance_group'] = pd.cut(df['distance'], bins=bins, labels=labels)
distance_dist = df['distance_group'].value_counts(normalize=True)
4.2 潮汐现象分析
早晚高峰期间,单车呈现明显的单向流动特征:
早高峰(7-9点):
- 从居民区向商务区集中
- 主要流向:西北向东南
晚高峰(17-19点):
- 从商务区向居民区回流
- 主要流向:东南向西北
这种潮汐现象导致某些区域在特定时段出现车辆供需失衡。
python复制# 空间热点分析
morning_df = df[(df['hour'] >= '07') & (df['hour'] <= '09')]
evening_df = df[(df['hour'] >= '17') & (df['hour'] <= '19')]
# 使用folium绘制热力图
import folium
from folium.plugins import HeatMap
m = folium.Map(location=[39.9, 116.4], zoom_start=12)
heat_data = [[row['start_latlon'][0], row['start_latlon'][1]] for _,row in morning_df.iterrows()]
HeatMap(heat_data).add_to(m)
m.save('morning_hotspots.html')
5. 用户行为分析
5.1 使用频次分布
用户使用频次呈现长尾分布:
- 1-3次:48.2%
- 4-6次:21.5%
- 7-10次:12.3%
-
10次:18.0%
工作日和周末的频次分布也有差异:
- 工作日:平均频次更高
- 周末:低频次用户占比更大
python复制# 用户频次统计
user_freq = df.groupby('userid')['orderid'].count()
# 频次分组
freq_groups = pd.cut(user_freq, bins=[0,3,6,10,100],
labels=['1-3次','4-6次','7-10次','>10次'])
freq_dist = freq_groups.value_counts(normalize=True)
5.2 用户粘性分析
定义高粘性用户为:
- 工作日使用6次及以上
- 周末使用3次及以上
分析发现:
- 高粘性用户占比约30%
- 这类用户贡献了约60%的订单量
- 主要特征是通勤刚需用户
python复制# 识别高粘性用户
heavy_users = user_freq[user_freq >= 6].index
heavy_user_orders = df[df['userid'].isin(heavy_users)].shape[0]
total_orders = df.shape[0]
heavy_user_ratio = heavy_user_orders / total_orders
6. 运营优化建议
基于上述分析,我提出以下优化建议:
6.1 动态调度策略
-
预测需求热点:
- 工作日早高峰前向商务区预调度
- 工作日晚高峰前向居民区预调度
- 周末午晚时段向餐饮集中区调度
-
路线优化:
python复制# 调度路线算法示例
def optimize_routing(start_points, end_points, n_bikes):
# 使用贪心算法匹配供需
matched_pairs = []
while start_points and end_points and n_bikes >0:
best_pair = find_closest_pair(start_points, end_points)
matched_pairs.append(best_pair)
n_bikes -= 1
return matched_pairs
6.2 用户激励措施
-
通勤套餐:
- 工作日包周/包月优惠
- 高峰时段奖励骑行
-
推荐系统:
python复制# 简单的协同过滤推荐
from sklearn.neighbors import NearestNeighbors
def recommend_users(target_user, user_features, n=5):
nn = NearestNeighbors(n_neighbors=n)
nn.fit(user_features)
distances, indices = nn.kneighbors([target_user])
return indices[0]
7. 项目扩展方向
这个项目还有多个可以深入的方向:
-
天气因素分析:
- 结合气象数据,分析不同天气条件下的使用模式
-
定价策略优化:
- 基于供需关系的动态定价模型
-
车辆维护预测:
- 基于使用频率预测车辆维护周期
python复制# 维护预测模型示例
from sklearn.ensemble import RandomForestRegressor
def predict_maintenance(usage_data):
X = usage_data[['ride_count','distance_sum','user_count']]
y = usage_data['maintenance_flag']
model = RandomForestRegressor()
model.fit(X, y)
return model
在实际操作中,我发现共享单车数据分析最关键的三个要点是:数据质量、特征工程和业务理解。特别是在处理地理空间数据时,坐标系的统一和距离计算的准确性会直接影响分析结果。另外,这个项目让我深刻体会到,好的数据分析不仅要发现规律,更要能为业务决策提供 actionable insights。