Python数据分析实战:用Pandas和Matplotlib预测共享单车租赁需求(附完整代码)

共享单车作为城市短途出行的解决方案,其租赁需求预测对运营调度至关重要。本文将带您从零开始,使用Python生态中的Pandas、Matplotlib和Scikit-learn构建完整的预测流程,不仅包含代码实现,更会深入每个环节的技术选型思考。

1. 数据探索:发现隐藏在数字背后的故事

拿到一份原始数据时,我们首先需要理解它的结构和内涵。共享单车数据通常包含以下关键字段:

import pandas as pd
df = pd.read_csv('bike_data.csv')
print(df.info())

典型的数据结构可能包含:

  • datetime: 精确到小时的时间戳
  • season: 季度编码(1-4)
  • weather: 天气状况分级
  • temp/atemp: 实际体感温度
  • humidity: 湿度百分比
  • windspeed: 风速
  • count: 总租赁量(目标变量)

数据可视化是发现规律的第一步。我们使用Matplotlib绘制24小时租赁量变化:

import matplotlib.pyplot as plt
df['hour'] = pd.to_datetime(df['datetime']).dt.hour
hourly_avg = df.groupby('hour')['count'].mean()

plt.figure(figsize=(12,6))
plt.plot(hourly_avg, marker='o', color='#3498db')
plt.title('Average Rentals by Hour of Day', pad=20)
plt.xlabel('Hour of Day')
plt.ylabel('Average Rentals')
plt.grid(alpha=0.3)
plt.xticks(range(24))
plt.show()

这个简单的折线图可能揭示出:

  • 早晚通勤高峰的明显波峰
  • 午间小高峰
  • 凌晨时段的低谷期

2. 特征工程:从原始数据到模型语言

原始数据很少能直接用于建模,特征工程是将业务理解转化为数学模型的关键步骤。

2.1 时间特征分解

时间戳包含丰富信息,我们需要将其分解为更有意义的特征:

def extract_time_features(df):
    dt = pd.to_datetime(df['datetime'])
    df['year'] = dt.dt.year
    df['month'] = dt.dt.month
    df['day'] = dt.dt.day
    df['hour'] = dt.dt.hour
    df['weekday'] = dt.dt.weekday  # 0-6对应周一到周日
    df['is_weekend'] = df['weekday'].isin([5,6]).astype(int)
    return df

2.2 天气特征处理

天气数据通常需要特殊处理:

原始值 处理建议 业务含义
1 保持 晴朗
2 合并 多云/薄雾
3 警告 小雪/小雨
4 剔除 极端天气
# 天气数据清洗示例
df['weather'] = df['weather'].replace(4, 3)  # 合并极端天气
df = df[df['weather'] != 4]  # 或直接剔除

2.3 温度特征转换

人体对温度的感知是非线性的,可以考虑:

df['temp_squared'] = df['temp'] ** 2
df['temp_cubed'] = df['temp'] ** 3

3. 数据可视化:多维度的洞察发掘

3.1 热力图分析

import seaborn as sns
corr = df[['temp', 'atemp', 'humidity', 'windspeed', 'count']].corr()
sns.heatmap(corr, annot=True, cmap='coolwarm')

3.2 箱线图异常值检测

plt.figure(figsize=(10,6))
sns.boxplot(x='hour', y='count', data=df)
plt.title('Rental Distribution by Hour')

4. 模型构建:从线性回归到集成方法

4.1 基准模型:Ridge回归

from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split

# 特征选择
features = ['season', 'holiday', 'workingday', 'weather', 
           'temp', 'atemp', 'humidity', 'windspeed',
           'year', 'month', 'hour', 'weekday', 'is_weekend']

X = df[features]
y = df['count']

# 数据分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# 模型训练
model = Ridge(alpha=1.0)
model.fit(X_train, y_train)

4.2 进阶模型:随机森林

from sklearn.ensemble import RandomForestRegressor

rf = RandomForestRegressor(n_estimators=100, max_depth=10)
rf.fit(X_train, y_train)

# 特征重要性可视化
importances = rf.feature_importances_
plt.barh(features, importances)
plt.title('Feature Importances')

4.3 模型评估指标

指标 公式 适用场景
MAE $\frac{1}{n}\sum y-\hat{y}
RMSE $\sqrt{\frac{1}{n}\sum(y-\hat{y})^2}$ 大误差惩罚
$1-\frac{\sum(y-\hat{y})^2}{\sum(y-\bar{y})^2}$ 解释方差比例
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

def evaluate(y_true, y_pred):
    print(f'MAE: {mean_absolute_error(y_true, y_pred):.2f}')
    print(f'RMSE: {np.sqrt(mean_squared_error(y_true, y_pred)):.2f}')
    print(f'R2: {r2_score(y_true, y_pred):.2f}')

5. 部署准备:从Jupyter到生产环境

5.1 模型持久化

import joblib
joblib.dump(model, 'bike_model.pkl')

# 加载模型
loaded_model = joblib.load('bike_model.pkl')

5.2 构建预测API

from flask import Flask, request, jsonify
app = Flask(__name__)

@app.route('/predict', methods=['POST'])
def predict():
    data = request.get_json()
    features = preprocess(data)  # 预处理函数
    prediction = loaded_model.predict([features])
    return jsonify({'prediction': prediction[0]})

在实际项目中,我发现天气数据的质量对预测结果影响最大。特别是在雨季,突然的天气变化会导致预测偏差增大约15%。解决方法是引入实时天气API数据,每小时更新一次预测模型。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐