使用混乱数据集构建数据清洗管道的实战指南
引言
根据CrowdFlower的调查,数据科学家花费60%的时间来组织和清理数据。本文将使用一个真实的数据集来构建数据清洗管道,该数据集包含近20万条食品配送记录,每条记录包含数十个特征,如配送时间、商品总数和店铺类别(例如墨西哥菜、泰国菜或美国菜)。
使用数据集预测食品配送时间
目标是准确估算从客户下订单到食品送达门口所需的时间。在这个数据项目中,任务是基于历史配送数据开发一个预测总配送时长的模型。但不会完成整个项目——即不会构建预测模型,而是使用项目中提供的数据集并创建数据清洗管道。
工作流程包含两个主要步骤。
数据探索
首先加载并查看数据集的前几行。
# 加载并预览数据集
import pandas as pd
df = pd.read_csv("historical_data.csv")
df.head()
输出结果如下。
该数据集包含记录订单创建时间和实际送达时间的日期时间列,可用于计算配送时长。还包含其他特征,如店铺类别、商品总数、小计和最低商品价格,使其适用于各种类型的数据分析。已经可以看到存在一些NaN值,将在后续步骤中更仔细地探索。
# 使用info()探索列
使用info()方法检查所有列名。将在整篇文章中使用此方法来查看列值计数的变化;这是缺失数据和整体数据健康状况的良好指标。
df.info()
输出结果如下。
可以看到有15列,但各列的非空值数量不同。这意味着某些列包含缺失值,如果处理不当可能会影响分析。最后一件事:created_at和actual_delivery_time的数据类型是对象;这些应该是日期时间。
构建数据清洗管道
在此步骤中,构建一个结构化的数据清洗管道,为建模准备数据集。每个阶段都解决常见问题,如时间戳格式、缺失值和不相关特征。
# 修复日期时间列的数据类型
在进行数据分析之前,需要修复显示时间的列。否则,之前提到的计算(actual_delivery_time - created_at)将会出错。
正在修复的内容:
created_at:下单时间
actual_delivery_time:食品送达时间
这两列存储为对象,因此为了能够正确进行计算,必须将它们转换为日期时间格式。可以使用pandas中的日期时间函数。代码如下。
import pandas as pd
df = pd.read_csv("historical_data.csv")
# 将时间戳字符串转换为日期时间对象
df["created_at"] = pd.to_datetime(df["created_at"], errors="coerce")
df["actual_delivery_time"] = pd.to_datetime(df["actual_delivery_time"], errors="coerce")
df.info()
输出结果如下。
从上面的截图可以看到,created_at和actual_delivery_time现在是日期时间对象。
在关键列中,store_primary_category的非空值最少(192,668),这意味着它的缺失数据最多。这就是首先清理它的原因。
# 使用mode()进行数据插补
数据集中最混乱的列之一是store_primary_category,从其高缺失值数量可见一斑。它告诉我们有哪些类型的食品店铺可用,如墨西哥菜、美国菜和泰国菜。然而,许多行缺少此信息,这是一个问题。例如,它可能限制我们分组或分析数据的方式。那么如何修复呢?
将填充这些行而不是删除它们。为此,将使用更智能的插补方法。
编写一个字典,将每个store_id映射到其最频繁的类别,然后使用该映射填充缺失值。让我们在操作之前查看数据集。
代码如下。
import numpy as np
# 全局最频繁类别作为回退
global_mode = df["store_primary_category"].mode().iloc[0]
# 构建店铺级别到最频繁类别的映射(快速且稳健)
store_mode = (
df.groupby("store_id")["store_primary_category"]
.agg(lambda s: s.mode().iloc[0] if not s.mode().empty else np.nan)
)
# 使用店铺级别模式填充缺失类别,然后回退到全局模式
df["store_primary_category"] = (
df["store_primary_category"]
.fillna(df["store_id"].map(store_mode))
.fillna(global_mode)
)
df.info()
输出结果如下。
从上面的截图可以看到,store_primary_category列现在具有更高的非空计数。但使用以下代码再次检查。
df["store_primary_category"].isna().sum()
输出结果显示NaN值的数量。为零;已经消除了所有NaN值。
让我们看看插补后的数据集。
# 删除剩余的NaN
在上一步中,修正了store_primary_category,但您注意到什么了吗?各列的非空计数仍然不匹配!
这清楚地表明数据集的某些部分仍然存在缺失值。在数据清理方面,有两个选项:
填充这些缺失值
删除它们
鉴于该数据集包含近20万行,可以承受丢失一些。对于较小的数据集,需要更加谨慎。在这种情况下,建议分析每一列,建立标准(决定如何填充缺失值——使用均值、中位数、最频繁值或特定领域的默认值),然后填充它们。
要删除NaN,将使用pandas库中的dropna()方法。设置inplace=True以直接将更改应用到DataFrame,而无需再次分配。让我们看看此时的数据集。
代码如下。
df.dropna(inplace=True)
df.info()
输出结果如下。
从上面的截图可以看到,每列现在具有相同数量的非空值。
让我们看看所有更改后的数据集。
接下来可以做什么?
现在有了一个干净的数据集,接下来可以做一些事情:
执行EDA以了解配送模式。
设计新特征,如配送小时或忙碌配送员比率,为分析增添更多意义。
分析变量之间的相关性以提高模型性能。
构建不同的回归模型并找到性能最佳的模型。
使用性能最佳的模型预测配送时长。
最终思考
在本文中,通过解决常见的数据质量问题清理了真实的数据集,例如修复不正确的数据类型和处理缺失值。构建了一个针对此数据项目的简单数据清洗管道,并探索了潜在的后续步骤。
真实世界的数据集可能比您想象的更混乱,但也有许多方法和技巧来解决这些问题。感谢阅读!
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)或者 我的个人博客 https://blog.qife122.com/
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码

公众号二维码


浙公网安备 33010602011771号