您的当前位置:首页>全部文章>文章详情

EDA 代码教程:带你轻松拿捏数据分析!(exploredata analusis)

发表于:2022-03-02 16:02:03浏览:2873次TAG:

1. Intro
Hello,各位!今天我们要一起探索数据分析!你是不是经常听到“EDA”这个词,但又觉得很神秘?别担心,这篇教程会手把手带你入门,保证你轻松拿捏!
📌案例背景:我们今天研究的是产品销售数据,看看不同因素如何影响销售额。

🛠 2. 导入必要的库

import pandas as pd
import numpy as  np
import seaborn as sns
import matplotlib.pyplot as plt

pandas:数据处理神器,负责计算数据。
numpy:数学计算画图的小能手。
seaborn:画出好看的统计图。
matplotlib.pyplot:基础绘图工具,配合seaborn使用会更好用。
👁 3.检查数据格式

通常对于数据分析 我们使用.csv格式的文件进行分析()逗号分隔数据
今天,咱们就.csv文件展开示范哈。💕💕💕

📂 4. 数据加载:如何高效读取多个销量数据文件?

目标

在数据分析的第一步,我们通常需要加载多个数据集。这里我们有两类数据:
产品销量数据(sales data) 📈
天气数据(weather data) ⛅
我们将使用 pandas 的 read_csv() 方法批量读取这些文件,并探索它们的结构。

🛠 代码实现(一件三联领取代码和数据集哦)

销量数据文件列表

sales_files = [ ‘DailySales_R1.csv’, ‘DailySales_R2.csv’, ‘DailySales_R3.csv]

天气数据文件列表

weather_files = [ ‘99322123.csv’,’2004sales.csv’]

批量读取销量数据

sales_data = [pd.read_csv(file) for file in sales_files]

批量读取天气数据

weather_data = [pd.read_csv(file) for file in weather_files]

查看部分数据

sales_sample = sales_data[0].head() weather_sample = weather_data[0].head()

sales_sample, weather_sample

代码解析
1️⃣ 为什么要存成列表?
在 sales_data 和 weather_data 这两个变量里,我们使用了列表推导式(List Comprehension)来存储多个年份的数据集。这样做的好处:

  1. 代码简洁:用一行代码就能遍历所有文件并读取它们,不需要写多个 pd.read_csv() 语句。
  2. 可扩展性强:如果未来要增加新的数据文件,我们只需要在 sales_files 或 weather_files 里添加新的文件名,而不需要修改 read_csv() 代码。

2️⃣ 为什么用 pd.read_csv() 读取数据?
pandas 的 read_csv() 是最常见的数据读取函数
✅ 快速高效: pandas 经过优化,读取 CSV 文件的速度比 Python 内置的 open() + csv.reader() 更快。
✅ 自动识别数据类型:可以自动解析日期、字符串、数值等数据类型(虽然默认行为有时候需要调整)。
✅ 易于操作:它返回一个 DataFrame ,可以直接用于数据分析。

❌ 反面例子(不推荐做法,可以用,但是太sb了)

不推荐:逐个手动读取

df1 = pd.read_csv(‘sales_2021.csv’) df2 = pd.read_csv(‘sales_2022.csv’) df3 = pd.read_csv(‘sales_2023.csv’) df4 = pd.read_csv(‘sales_2024.csv’)

sales_data = [df1, df2, df3, df4]

为什么不好?
代码冗长,如果有 10 个年份的数据,需要写 10 行 pd.read_csv() 。
不易维护,如果要添加新的数据年份,必须手动修改代码,而不是简单地扩展文件列表。

3️⃣ head() 重要性

sales_sample = sales_data[0].head() weather_sample = weather_data[0].head()

✅ 快速预览数据: head(5) 只取前 5 行数据,避免直接打印整个数据集,防止终端崩溃。
✅ 检查数据格式:可以快速确认数据是否正确加载,例如:
列名是否符合预期? 是否有缺失值?
数据类型是否正确?

🚀 小挑战:尝试优化数据读取

💡 现在我们已经学会了如何批量读取数据,你能优化 pd.read_csv() 的参数,让它更高效吗?比如:
使用 low_memory=False 解决 DtypeWarning 问题? 用 usecols 只加载需要的列,提高性能?
结合 dtype 指定列的数据类型?
思考:

  1. 为什么 pd.read_csv() 可能会发出 DtypeWarning ?
  2. 如果 CSV 文件很大,如何优化读取速度?(评论区@博主哦❤❤❤)

🧹 5. 数据清理:如何正确解析天气数据?

在数据分析过程中,原始数据通常会包含许多编码过的信息,比如:

温度(TMP) 🌡
露点(DEW) 💦
海平面气压(SLP) 🌍
这些变量对销量分析至关重要,因为天气因素可能会影响消费者的购买决策,比如:雨天是否影响商店客流量?。在这一部分,我们会解码这些天气变量,并清理数据,使其更易于分析。

代码

解析关键天气变量

温度 (TMP), 露点 (DEW), 海平面气压 (SLP) 是主要的分析变量

weather_combined[‘temperature’] = weather_combined[‘TMP’].str.split(‘,’, expand=True)[0].a weather_combined[‘dew_point’] = weather_combined[‘DEW’].str.split(‘,’, expand=True)[0].ast weather_combined[‘pressure’] = weather_combined[‘SLP’].str.split(‘,’, expand=True)[0].asty

将日期转换为标准的 datetime 格式

weather_combined[‘date’] = pd.to_datetime(weather_combined[‘DATE’], errors=’coerce’)

删除无效日期或关键天气变量缺失的行

weather_combined_cleaned = weather_combined.dropna(subset=[‘date’, ‘temperature’, ‘dew_poi

查看清理后的数据

weather_combined_cleaned.head()

🤔 代码解析

1️⃣ 为什么要拆分 TMP、DEW 和 SLP?
在一些数据集中,天气变量通常以 10,0 这种格式存储,其中:
10 代表测量值(如温度 10°C)。
0 代表质量控制标识符,不需要使用。所以我们使用:
.str.split(‘,’, expand=True)[0]

✅ 分割字符串,只提取第一部分(真正的数值)。
✅ 去除不必要的额外信息,确保数据格式一致。
❌ 反面例子

weather_combined[‘temperature’] = weather_combined[‘TMP’]

直接读取 TMP 列,会包含额外的标识信息,导致数据格式不对,可能会引发 ValueError 。

2️⃣ 为什么 astype(float) / 10 ?
在某些天气数据集中,温度、露点和气压通常被放大了 10 倍,例如:
温度 125 实际上表示 12.5°C 。 露点 85 代表 8.5°C 。
气压 10120 代表 1012.0 hPa 。
✅ astype(float) / 10 确保数值正确缩放,使数据符合实际单位。
❌ 反面例子

weather_combined[‘temperature’] = weather_combined[‘TMP’].astype(float)

忘记 / 10 ,可能导致温度从 12.5°C 变成 125°C ,直接变成了三味真火!

3️⃣ 为什么转换日期格式?
weather_combined[‘date’] = pd.to_datetime(weather_combined[‘DATE’], errors=’coerce’)

✅ pd.to_datetime() 确保时间格式一致,方便后续分析和合并数据。
✅ errors=’coerce’ 防止错误格式的日期引发崩溃,任何无法解析的日期都会变成 NaT (缺失值)。
❌ 反面例子

weather_combined[‘date’] = weather_combined[‘DATE’]

为什么不好?
可能导致 date 仍然是字符串,无法进行日期计算。 不能用于时间序列分析或数据合并。

4️⃣ 为什么删除缺失数据?
weather_combined_cleaned = weather_combined.dropna(subset=[‘date’, ‘temperature’, ‘dew_poi

✅ 确保数据完整,防止后续分析出现错误。
✅ 减少无意义的缺失值行,提高模型的准确性。
❌ 反面例子

weather_combined_cleaned = weather_combined

如果不删除 NaN ,后续的统计分析或机器学习模型可能会报错。

总结

在这一步,我们: ✅ 解析了天气变量(温度、露点、气压),转换成标准单位。
✅ 将日期格式标准化,便于分析。
✅ 清理了缺失值,保证数据完整性。
💡 思考:

  1. 你能找到天气变量与销量之间的关系吗?
  2. 除了温度、露点和气压,还有哪些天气因素可能影响销量?
    🚀 继续加油,下一步我们将合并销量数据和天气数据,看看天气究竟会如何影响销售趋势!📊

🔗 6. 数据合并:销量数据与天气数据如何对齐?

目标

在数据分析中,我们通常需要合并不同来源的数据,比如:
销量数据 📈:包含每天的产品销售情况。
天气数据 🌦:记录当天的气象条件。
但这些数据可能没有完美匹配的时间戳(例如,一个数据是每天更新,另一个可能是每小时记录),所以我们需要使用“最近匹配”策略来对齐数据。

代码实现

合并所有销量数据到一个 DataFrame

sales_combined = pd.concat(sales_data, ignore_index=True)

将销量数据中的 ‘Report Date’ 转换为 datetime 格式,以便正确对齐

sales_combined[‘report_date’] = pd.to_datetime(sales_combined[‘Report Date’], errors=’coer

删除无效或缺失的日期,确保数据质量

sales_cleaned = sales_combined.dropna(subset=[‘report_date’])

按时间对齐并合并销量数据与天气数据

merged_data = pd.merge_asof( sales_cleaned.sort_values(‘report_date’), # 按日期排序销量数据 weather_combined_cleaned.sort_values(‘date’), # 按日期排序天气数据 left_on=’report_date’, # 以销量数据的 report_date 作为左键 right_on=’date’, # 以天气数据的 date 作为右键
direction=’nearest’ # 采用最近时间匹配方式
)

查看合并后的数据

merged_data.head()

🤔 代码解析

1️⃣ 为什么要用 pd.concat() ?
在 sales_data 变量中,我们存储了多个年份的销量数据(如 2021、2022、2023…)。

sales_combined = pd.concat(sales_data, ignore_index=True)

✅ 合并多个 DataFrame,形成一个完整的销量数据集。
✅ ignore_index=True 重置索引,防止多个 DataFrame 合并后索引混乱。
❌ 反面例子

sales_combined = sales_data[0] # 仅使用第一个年份的数据

只使用 2021 年的数据,忽略了其他年份的销量数据,导致分析结果不完整。

2️⃣ 为什么要转换日期格式?
sales_combined[‘report_date’] = pd.to_datetime(sales_combined[‘Report Date’], errors=’coer

✅ pd.to_datetime() 标准化日期格式,确保不同格式的日期可以正确解析。
✅ errors=’coerce’ 自动处理无效日期,如果某个值不能解析成日期,就会变成 NaT (缺失值)。
❌ 反面例子

sales_combined[‘report_date’] = sales_combined[‘Report Date’]

可能导致 report_date 仍然是字符串,无法用于时间序列分析或数据合并。

3️⃣ 为什么要删除无效的日期?
sales_cleaned = sales_combined.dropna(subset=[‘report_date’])

✅ 确保数据完整,避免时间戳为空的记录干扰分析。
✅ 让 report_date 这一列成为一个可靠的时间索引,避免合并时出现问题。
❌ 反面例子

sales_cleaned = sales_combined

如果不删除 NaN 值, merge_asof() 可能会失败或导致不正确的匹配。

4️⃣ 为什么用 pd.merge_asof() ?

在合并销量数据和天气数据时,我们遇到了一个挑战:
销量数据 可能是每天一条记录 📊
天气数据 可能是每小时一条记录 🌦
所以,我们不能用普通的 merge() ,因为它要求完全匹配的时间戳。我们使用 merge_asof() 来匹配最近的时间戳:

merged_data = pd.merge_asof( sales_cleaned.sort_values(‘report_date’), weather_combined_cleaned.sort_values(‘date’), left_on=’report_date’,
right_on=’date’, direction=’nearest’
)

✅ 自动匹配最近的天气数据,确保销量数据和天气信息合理对应。
✅ 适用于不同时间粒度的数据集(如“日数据”对“小时数据”)。
❌ 反面例子

merged_data = pd.merge(sales_cleaned, weather_combined_cleaned, on=’report_date’)

merge() 只能匹配完全相同的时间戳,如果 report_date 和 date 不完全一致,数据可能会丢失。

总结

在这一步,我们: ✅ 合并了多个年份的销量数据,形成完整的数据集。
✅ 清理了日期格式,确保数据的一致性。
✅ 使用 merge_asof() 进行“最近匹配”,对齐销量数据和天气数据。
💡 思考:

  1. 你能找到天气和销量之间的关系吗?
  2. 你觉得天气对哪些产品的销量影响最大?(比如冷饮、雨具等)

📊 7. 数据探索与可视化:销量与天气的关系

目标

现在我们已经成功合并了销量数据和天气数据,接下来要探索它们的特征:
销量的基本统计特征(如总销量、平均销量等)。销量随时间的变化趋势 📈。
天气变量随时间的变化趋势 🌡。
销量与天气之间的相关性 🤝。

代码实现

计算销量和天气变量的统计信息

summary_stats = merged_data[[‘Total Sales’, ‘Avg Sales per Store’, ‘temperature’, ‘dew_poi

绘制销量随时间的变化趋势

plt.figure(figsize=(12, 6))
plt.plot(merged_data[‘report_date’], merged_data[‘Total Sales’], color=’blue’, alpha=0.6) plt.title(‘ 销量随时间变化’, fontsize=14)
plt.xlabel(‘日期’, fontsize=12) plt.ylabel(‘总销量’, fontsize=12) plt.show()

绘制温度随时间的变化趋势

plt.figure(figsize=(12, 6))
plt.plot(merged_data[‘report_date’], merged_data[‘temperature’], color=’red’, alpha=0.6) plt.title(‘温度随时间变化’, fontsize=14)
plt.xlabel(‘日期’, fontsize=12)
plt.ylabel(‘温度 (°C)’, fontsize=12) plt.show()

计算销量与天气变量的相关性

correlation_matrix = merged_data[[‘Total Sales’, ‘Avg Sales per Store’, ‘temperature’, ‘de

返回统计摘要和相关性矩阵

summary_stats, correlation_matrix

代码解析
1️⃣ 为什么要用 describe() ?
summary_stats = merged_data[[‘Total Sales’, ‘Avg Sales per Store’, ‘temperature’, ‘dew_poi

✅ describe() 计算数据的基本统计信息,如:
均值(mean):销量的平均水平 标准差(std):销量的波动程度
最小值(min)/最大值(max):销量的范围
❌ 反面例子

summary_stats = merged_data.mean()

mean() 只会计算均值,不会提供标准差、最小值、最大值等关键信息。

2️⃣ 为什么用 plt.plot() 来绘制时间序列?

plt.plot(merged_data[‘report_date’], merged_data[‘Total Sales’], color=’blue’, alpha=0.6)

✅ plt.plot() 适用于连续数据(时间序列),可以清楚地显示销量随时间的变化趋势。
✅ color=’blue’ 使销量曲线更容易区分。
✅ alpha=0.6 使曲线半透明,增强可视化效果。
❌ 反面例子

plt.bar(merged_data[‘report_date’], merged_data[‘Total Sales’], color=’blue’)

柱状图(bar)适用于离散数据,而时间序列数据是连续的,应该用折线图(line plot)。

3️⃣ 为什么要分析温度随时间的变化?
plt.plot(merged_data[‘report_date’], merged_data[‘temperature’], color=’red’, alpha=0.6)

✅ 直观地查看气温的季节性变化(如夏季温度高、冬季温度低)。
✅ 结合销量数据,看看销量是否受气温影响(如冷饮销量是否在高温时上升)。
❌ 反面例子

plt.scatter(merged_data[‘report_date’], merged_data[‘temperature’], color=’red’)

散点图(scatter plot)适用于观察离散点分布,但不能清晰展示趋势变化。

4️⃣ 为什么要计算相关性?
correlation_matrix = merged_data[[‘Total Sales’, ‘Avg Sales per Store’, ‘temperature’, ‘de

✅ corr() 计算变量之间的线性相关性:
正相关(值接近 1):两个变量同时增加或减少,例如气温上升时冷饮销量上升。
负相关(值接近 -1):一个变量增加时,另一个变量减少,例如降水量增加时户外用品销量下降。
无相关(值接近 0):两个变量之间没有明显的线性关系。
❌ 反面例子

correlation_matrix = merged_data[[‘Total Sales’, ‘temperature’]].cov()

cov() 计算鞋方差,但协方差的数值大小依赖于变量的单位,不如相关系数(correlation coefficient)直观。

💡 思考:

  1. 你能找到天气与销量之间的关联吗?

  2. 哪些天气变量对销量影响最大?(温度?气压?露点?)
    🚀 继续加油!下一步我们将深入分析销量的模式,看看如何挖掘更多商业价值!📊

🔥 8. 特征工程:让数据更“聪明”!

目标

在这一部分,我们要对数据进行特征工程(Feature Engineering),让它更适合建模:

  1. 清理异常值,确保数据质量。
  2. 提取时间特征 ⏳,如星期几、小时等。
  3. 转换时间特征,使用正弦/余弦(sin/cos)编码,让时间信息更加平滑。(可以参考我时间序列的文章)

🛠 代码实现

这可根据作业要求改 但是作业要求官网还没发我

过滤异常天气数据,确保合理范围

weather_cleaned = merged_data[ (merged_data[‘temperature’] < 50) & # 温度不超过 50°C (merged_data[‘dew_point’] < 50) & # 露点不超过 50°C
(merged_data[‘pressure’] < 1500) # 气压不超过 1500 hPa
]

提取时间特征:星期几和小时

weather_cleaned[‘day_of_week’] = weather_cleaned[‘report_date’].dt.dayofweek # 星期一=0,星
weather_cleaned[‘hour_of_day’] = weather_cleaned[‘report_date’].dt.hour # 24 小时制

使用正弦和余弦变换时间特征

weather_cleaned[‘day_sin’] = np.sin(2 np.pi weather_cleaned[‘day_of_week’] / 7) weather_cleaned[‘day_cos’] = np.cos(2 np.pi weather_cleaned[‘day_of_week’] / 7) weather_cleaned[‘hour_sin’] = np.sin(2 np.pi weather_cleaned[‘hour_of_day’] / 24) weather_cleaned[‘hour_cos’] = np.cos(2 np.pi weather_cleaned[‘hour_of_day’] / 24)

选择用于建模的特征

model_data = weather_cleaned[[ ‘Total Sales’, # 销量
‘Avg Sales per Store’, # 平均单店销量
‘temperature’, # 温度 ‘dew_point’, # 露点 ‘pressure’, # 气压
‘day_sin’, ‘day_cos’, # 周期性特征(星期几)
‘hour_sin’, ‘hour_cos’ # 周期性特征(小时)
]]

查看数据描述统计信息

model_data_description = model_data.describe() print(model_data_description)

🤔 代码解析

1️⃣ 为什么要清理异常天气数据?
weather_cleaned = merged_data[ (merged_data[‘temperature’] < 50) & (merged_data[‘dew_point’] < 50) & (merged_data[‘pressure’] < 1500)
]

✅ 去除异常值,确保数据合理性:
temperature < 50 避免极端温度,如 100°C 这种不可能的情况。
dew_point < 50 露点不应过高,否则数据可能有误。
pressure < 1500 气压不应异常偏高。
❌ 反面例子

weather_cleaned = merged_data

如果不筛选异常数据,极端值可能会影响模型的准确性,比如异常高温导致销量预测错误。

2️⃣ 为什么要提取“星期几”和“小时”信息?
weather_cleaned[‘day_of_week’] = weather_cleaned[‘report_date’].dt.dayofweek weather_cleaned[‘hour_of_day’] = weather_cleaned[‘report_date’].dt.hour

✅ 时间特征对销量影响很大:
不同星期的销量模式可能不同(周末销量可能更高)。 不同时间段的销量不同(早晨 vs. 晚上)。
❌ 反面例子

weather_cleaned[‘day_of_week’] = weather_cleaned[‘report_date’]

直接使用日期作为特征,模型无法理解日期的周期性变化。

3️⃣ 为什么要用 sin/cos 变换时间特征?
weather_cleaned[‘day_sin’] = np.sin(2 np.pi weather_cleaned[‘day_of_week’] / 7) weather_cleaned[‘day_cos’] = np.cos(2 np.pi weather_cleaned[‘day_of_week’] / 7)

weather_cleaned[‘hour_sin’] = np.sin(2 np.pi weather_cleaned[‘hour_of_day’] / 24) weather_cleaned[‘hour_cos’] = np.cos(2 np.pi weather_cleaned[‘hour_of_day’] / 24)
✅ 时间是周期性的! 星期一和星期日虽然数值上相差 6,但它们应该是“相邻”的。
✅ sin/cos 变换让模型更容易理解时间特征,避免突变(如 0 → 6 跳跃)。
❌ 反面例子

weather_cleaned[‘day_of_week_encoded’] = weather_cleaned[‘day_of_week’]

这样会让模型认为星期一(0)和星期六(6)相差很远,但它们在实际数据模式中可能很相似。

4️⃣ 为什么要选择这些特征?
model_data = weather_cleaned[[
‘Total Sales’, ‘Avg Sales per Store’, ‘temperature’, ‘dew_point’, ‘pressure’, ‘day_sin’, ‘day_cos’, ‘hour_sin’, ‘hour_cos’
]]

✅ 销量相关特征:
Total Sales 代表销量目标变量。
Avg Sales per Store 代表单店销量情况。
✅ 天气相关特征:
temperature 可能影响某些商品销量(如冷饮)。 dew_point 可能影响舒适度,从而影响购买行为。 pressure 可能与天气变化有关。
✅ 时间相关特征:
day_sin, day_cos 让模型理解“星期几”的周期性影响。
hour_sin, hour_cos 让模型理解“一天中的不同时刻”对销量的影响。
❌ 反面例子

model_data = weather_cleaned[[‘Total Sales’, ‘temperature’, ‘pressure’]]

缺少时间特征,模型无法识别一天中销量的模式。 少考虑露点等其他变量,可能影响预测准确性。

总结

在这一步,我们: ✅ 清理了异常值,确保数据质量。
✅ 提取了时间特征,让模型理解销量的时间模式。
✅ 用 sin/cos 变换,让时间特征更平滑,帮助机器学习模型更好地学习周期性信息。

💡 思考:

  1. 你能发现哪些时间模式?周末销量是否更高?
  2. 天气特征对销量的影响是怎样的?
    🚀 继续加油!下一步我们将进入模型训练和分析阶段,看看天气和时间如何影响销量!📊

🤖 9. 线性回归:预测销量与天气的关系

目标

在这一步,我们将使用 线性回归(Linear Regression) 来预测销量:

  1. 数据清理 🧹:去除 NaN 值,确保数据完整。
  2. 拆分数据集 📊:将数据划分为训练集和测试集。
  3. 训练模型 🏋️‍♂️:用 天气特征和时间特征 来预测销量。
  4. 模型评估 📉:使用 MAE、MSE 和 R² 评估模型表现。

代码实现

from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

创建示例数据

data = {
‘total_sales’: [500, 600, 700, 800, np.nan, 900],
‘temperature’: [10, 12, 14, 13, 15, 11],
‘dew_point’: [5, 6, 7, 6, 7, 5],
‘pressure’: [1015, 1013, 1014, 1012, 1016, 1013],
‘day_sin’: [0.5, 0.6, 0.7, 0.5, 0.8, 0.6],
‘day_cos’: [0.5, 0.4, 0.3, 0.5, 0.2, 0.4],
‘hour_sin’: [0.2, 0.4, 0.6, 0.8, 0.9, 0.1],
‘hour_cos’: [0.8, 0.6, 0.4, 0.2, 0.1, 0.9],
}
model_data = pd.DataFrame(data)

处理 NaN 值

nan_rows = model_data[model_data[‘total_sales’].isna()] # 查找 NaN 行 model_data_cleaned = model_data.dropna(subset=[‘total_sales’]) # 删除 NaN 行 nan_count_after = model_data_cleaned[‘total_sales’].isna().sum() # 重新检查 NaN 计数

划分特征 (X) 和目标变量 (y)

X = model_data_cleaned[[‘temperature’, ‘dew_point’, ‘pressure’, ‘day_sin’, ‘day_cos’, ‘hou y = model_data_cleaned[‘total_sales’]

划分训练集和测试集(70% 训练,30% 测试)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

训练线性回归模型

linear_model = LinearRegression() linear_model.fit(X_train, y_train)

预测测试数据

y_pred = linear_model.predict(X_test)

计算评估指标

mae = mean_absolute_error(y_test, y_pred) # 平均绝对误差
mse = mean_squared_error(y_test, y_pred) # 均方误差
r2 = r2_score(y_test, y_pred) # R² 分数

mae, mse, r2, nan_rows, nan_count_after

代码解析

1️⃣ 为什么要去除 NaN 值?
nan_rows = model_data[model_data[‘total_sales’].isna()] model_data_cleaned = model_data.dropna(subset=[‘total_sales’])

✅ 机器学习模型不能处理 NaN 值,必须先删除或填充。
✅ 这里我们删除了 total_sales 为空的行,确保目标变量完整。
❌ 反面例子

model_data_cleaned = model_data

如果 total_sales 里有 NaN,模型训练时会报错( ValueError: Input contains NaN )。

2️⃣ 为什么要拆分训练集和测试集?
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

✅ 训练集用于训练模型,测试集用于评估模型的泛化能力。
✅ test_size=0.2 表示 80% 的数据用于训练,20% 用于测试。
✅ random_state=42 保证每次运行的拆分结果相同,方便复现。
❌ 反面例子

X_train, X_test, y_train, y_test = train_test_split(X, y)

没有 test_size ,默认会使用 75% 训练,25% 测试,不利于控制比例。没有 random_state ,每次拆分都不同,导致结果不可复现。

3️⃣ 为什么用线性回归模型?
linear_model = LinearRegression() linear_model.fit(X_train, y_train)

✅ 线性回归适用于分析销量与天气变量之间的线性关系。
✅ 适合初步建模,易于解释。
❌ 反面例子

linear_model = None

不训练模型,就无法进行预测,整个分析流程失效。

4️⃣ 如何评估模型?
mae = mean_absolute_error(y_test, y_pred) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred)

✅ MAE(Mean Absolute Error,平均绝对误差):
衡量预测值与真实值的平均绝对偏差,单位与 total_sales 一致。
✅ MSE(Mean Squared Error,均方误差):
对误差进行平方,让较大的误差更加突出。
✅ R²(决定系数):
衡量模型解释目标变量的能力:
接近 1:模型表现好。
接近 0:模型几乎没用。
❌ 反面例子

accuracy = (y_pred == y_test).mean()

accuracy 只适用于分类问题,而这里是回归问题。

总结

在这一步,我们: ✅ 去除了 NaN 值,确保数据完整。
✅ 划分了训练集和测试集,避免数据泄漏。
✅ 训练了线性回归模型,分析天气和时间特征对销量的影响。
✅ 计算了模型性能指标,评估其准确性。
💡 思考:

  1. 你的模型的 R² 值是多少? 这个模型能很好地预测销量吗?
  2. 你认为哪些特征最重要? 是否可以添加更多特征来提高预测能力?
    🚀 继续加油!下一步,我们将尝试不同的模型,比如 决策树回归 或 随机森林,看看能否提高销量预测的准确性! 📊

🚀 10. 多项式回归 & 时间序列分析:探索更强预测能力!

目标

在本节中,我们将尝试更复杂的回归方法,并探索时间序列模式:

  1. 多项式回归 🏋️‍♂️:添加交互特征,提高模型预测能力。
  2. 时间序列分析 ⏳:分析销量的长期趋势,并进行平稳性检测。

代码实现

🔹 10.1 多项式回归

引入必要的库

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler

创建多项式回归流水线

pipeline = Pipeline([
(‘scaler’, StandardScaler()), # 归一化数据
(‘poly’, PolynomialFeatures(degree=2, include_bias=False)), # 生成交互特征
(‘model’, LinearRegression()) # 线性回归
])

训练模型

pipeline.fit(X_train, y_train)

预测测试集

y_pred_refined = pipeline.predict(X_test)

评估模型

mae_refined = mean_absolute_error(y_test, y_pred_refined) mse_refined = mean_squared_error(y_test, y_pred_refined) r2_refined = r2_score(y_test, y_pred_refined)

mae_refined, mse_refined, r2_refined

🤔 多项式回归解析

1️⃣ 为什么要使用多项式特征?
(‘poly’, PolynomialFeatures(degree=2, include_bias=False))

✅ 自动生成特征交互项,比如:

temperature * dew_point
temperature² (非线性关系)
✅ 适用于非线性数据集,比如销量与天气的关系。
❌ 反面例子

(‘model’, LinearRegression()) # 仅使用线性关系

如果销量与天气的关系是非线性的,普通线性回归可能效果不好。

2️⃣ 为什么要标准化数据?
(‘scaler’, StandardScaler())

✅ 确保特征缩放一致,避免数值范围大的变量影响模型训练。
❌ 反面例子

pipeline = Pipeline([
(‘poly’, PolynomialFeatures(degree=2, include_bias=False)), (‘model’, LinearRegression())
])

没有标准化,可能导致某些变量主导模型,影响回归效果。

3️⃣ 如何评估改进后的模型?
mae_refined = mean_absolute_error(y_test, y_pred_refined) mse_refined = mean_squared_error(y_test, y_pred_refined) r2_refined = r2_score(y_test, y_pred_refined)

✅ 对比 r² 分数,如果 r²_refined > r² ,说明多项式回归比普通线性回归更好。
❌ 反面例子

print(y_test - y_pred_refined)

直接看误差没有定量衡量标准,难以比较模型优劣。

🔹 10.2 时间序列分析

from statsmodels.tsa.seasonal import seasonal_decompose from statsmodels.tsa.stattools import adfuller

处理时间格式

time_series_data = merged_data[[‘Total Sales’, ‘temperature’, ‘report_date’]].copy() merged_data[‘report_date’] = pd.to_datetime(time_series_data[‘report_date’])

按日期聚合销量

daily_sales = time_series_data.groupby(time_series_data[‘report_date’].dt.date)[‘Total Sal

平稳性检验(ADF 检验)

adf_test = adfuller(daily_sales, autolag=’AIC’) adf_statistic, adf_p_value = adf_test[0], adf_test[1]

绘制销量趋势

plt.figure(figsize=(12, 6))
plt.plot(daily_sales, label=’Daily Sales Volume’, color=’blue’) plt.title(‘📊 每日销量趋势’, fontsize=14)
plt.xlabel(‘日期’, fontsize=12) plt.ylabel(‘销量’, fontsize=12) plt.legend()
plt.grid(True) plt.show()

adf_statistic, adf_p_value

时间序列分析解析

1️⃣ 为什么要做时间序列分解?
daily_sales = time_series_data.groupby(time_series_data[‘report_date’].dt.date)[‘Total Sal

✅ 聚合每日销量,观察销量随时间的变化趋势。
✅ 识别季节性波动(如周末销量是否更高)。
❌ 反面例子

daily_sales = time_series_data[‘Total Sales’]

没有按日期聚合,数据可能仍然是小时级别,不适合分析长期趋势。

2️⃣ 为什么要做 ADF(Augmented Dickey-Fuller)检验?
adf_test = adfuller(daily_sales, autolag=’AIC’) adf_statistic, adf_p_value = adf_test[0], adf_test[1]

✅ 检查时间序列是否平稳:
p 值 < 0.05,数据是平稳的,可以直接建模。
p 值 > 0.05,数据是非平稳的,需要差分(Differencing)。
❌ 反面例子

daily_sales.plot()

只画图无法判断数据是否平稳,必须用统计检验。

3️⃣ 如何解释时间序列图?
plt.plot(daily_sales, label=’Daily Sales Volume’, color=’blue’)

✅ 可以发现哪些模式?
是否有上升趋势 📈?
是否存在周期性变化 ⏳(如周末销量更高)?
❌ 反面例子

plt.bar(daily_sales.index, daily_sales.values)

时间序列适合折线图,而柱状图不适用于连续数据。

总结

在本节中,我们: ✅ 使用了多项式回归,提高销量预测能力。
✅ 分析了时间序列模式,研究销量随时间的变化。
✅ 使用 ADF 检验检查了数据的平稳性,为未来建模做准备。
💡 思考:

  1. 你的销量数据是否有明显的季节性变化?
  2. 你的模型 r² 是否比普通线性回归更高?

本期文章就到这里了,如果想知道我们应该怎么用这些代码进行更深入的有效的分析,请关注我的下一篇文章💕

0.095213s