跳至主要内容

PySpark:如何从 DataFrame 中删除列

在 PySpark 中,我们可以使用 .drop("column_name") 从 DataFrame 删除单个列,或使用 .drop(["column1", "column2", ...]) 删除多个列。
· 6分钟 阅读

使用 AI 探索

数据清洗与准备是任何数据科学或数据工程项目中的关键步骤。为确保数据的质量与可靠性,我们需要识别并处理不一致、错误以及缺失值。

在处理大型数据集时,PySpark 尤其有用,因为它提供了高效的方法来清洗数据集。本文将聚焦一个常见的清洗任务:使用 PySpark 的 .drop() 和 .select() 方法从 DataFrame 中删除列。

想进一步了解 PySpark,请查看这门课程:Introduction to PySpark。

 

为何要在 PySpark DataFrame 中删除列?

出于多种原因,在数据预处理中删除列是常见操作。移除不必要或不相关的列可以显著减少需要处理的数据量。这将使数据集更精简、更易分析,并可能提升 PySpark 作业的性能。

此外,在为机器学习模型准备数据时,特征选择通常会删除对模型准确性无贡献或可能引入噪声的列。此步骤有助于构建更高效、更有效的模型。

最后,删除列也可以作为一种提升数据质量的策略。如果某一列包含大量缺失值或错误数据,将其移除可能是最佳选择。

如何从 PySpark DataFrame 中删除单个列

假设我们有一个包含五个列的 DataFrame df:player_name、player_position、team、minutes_played 和 score。其中 minutes_played 列存在大量缺失值,因此我们希望将其删除。

在 PySpark 中,我们可以使用 .drop() 方法从 DataFrame 中删除单个列。

语法为 df.drop("column_name"),其中:

  • df 是要从中删除列的 DataFrame
  • column_name 是要删除的列名。

df.drop() 方法会返回一个已移除指定列的新 DataFrame。

删除列的方法如下:

df_dropped = df.drop("minutes_played")

如何从 PySpark DataFrame 中删除多个列

假设我们想分析 DataFrame df,但不考虑球队或球员位置——因此需要同时删除这两列。实现这一点的方法不止一种,下面来看看选项。

要从 PySpark DataFrame 中删除多个列,我们可以向 .drop() 方法传入列名列表。有两种方式:

# 方式一:以列表形式传入列名
df_dropped = df.drop(["team", "player_position"])

# 方式二:分别作为独立参数传入列名
df_dropped = df.drop("team", "player_position")

或者,我们也可以链式调用多个 .drop()。虽然可行,但通常不被认为是最高效或最优雅的方法。每次调用都会创建一个新的 DataFrame,这在处理大型数据集时可能带来额外开销。

df_dropped = df.drop("team").drop("player_position")

按条件删除列

与其显式指定要删除的列,我们也可以反向思考,只选择满足特定条件或要求的列。这样,返回的 DataFrame 将不再包含不需要的列。

使用 .select()

我们可以在 PySpark 中结合列表推导与 .select() 方法,根据某些条件删除一个或多个列。该方法非常灵活,从简单到复杂的条件都能适用。

其语法为 df.select([col for col in df.columns if condition]),其中:

  • df 是您正在处理的 DataFrame。
  • condition 是用于筛选要保留列的条件。

让我们继续使用 DataFrame df,选择除 team 列之外的所有列:

df_sel = df.select([col for col in df.columns if col != "team"])

结合 .selectExpr() 的复杂条件

如果您熟悉 SQL,并且在筛选列时需要应用更复杂的条件,PySpark 的 .selectExpr() 方法是个强大的解决方案。它允许我们在 PySpark 代码中直接使用类 SQL 表达式来选择和处理列。

例如,考虑以下示例:

# 选择特定列并创建一个新的 'FullMatch' 列
df_sel = df.selectExpr("player_name", "player_position", "minutes_played >= 60 as FullMatch")

在这里,我们不仅仅是在排除某一列。我们还在:

  1. 选择 player_name 和 player_position 两列。
  2. 创建一个名为 FullMatch 的新列,用于指示球员是否打满一场比赛(60 分钟或以上)。

在简单列表推导不够用的场景中,.selectExpr() 的这种灵活性尤为重要。

最佳实践

当决定从 DataFrame 中删除列时,遵循一些最佳实践对于维护数据完整性、代码可读性和效率至关重要。

1. 备份数据:在修改 DataFrame 前,尤其是在删除列时,最好创建一份备份。这可以确保在需要时还原至原始数据。

df_backup = df.persist()  # 缓存 DataFrame,避免后续重复计算

2. 使用 inplace=False(默认)删除:默认情况下,.drop() 方法返回一个新 DataFrame,而不会修改原始数据。这通常更安全。如果您非常确定要修改原始 DataFrame,可以使用 inplace=True,但请谨慎操作。

df_dropped = df.drop("column_to_drop", inplace=False) # 默认行为

3. 记录您的决策:如果您在协作项目中工作,或预计未来会回看代码,建议添加注释,说明为何删除特定列。这类文档能为您和他人提供重要背景。

4. 考虑重命名列:与其删除列,不妨考虑是否可以重命名,尤其是在其中信息可能对未来分析仍有价值时。PySpark 提供了 .withColumnRenamed() 方法,帮助我们重命名列。

结论

在本教程中,我们学习了如何使用 .drop() 和 .select() 方法删除单列和多列。我们还介绍了在需要更复杂选择技术时,如何利用 SQL 表达式的替代方法。

如果您希望扩展技能并利用 PySpark 的强大能力,建议查看以下课程与资料:

常见问题

如何在 PySpark 中基于正则表达式删除列?

要在 PySpark 中基于正则表达式删除列,您可以使用列表推导配合 re 模块(用于正则表达式)过滤列名,然后将筛选结果传入 .drop() 方法。

如何在 PySpark 中删除同名列?

PySpark 不允许 DataFrame 中存在重复列名。如果数据源包含重复名称,在创建 DataFrame 时很可能会报错。最佳实践是在数据源或 DataFrame 创建阶段解决重复列名问题。

如何在 PySpark 中删除只包含空值的列?

要在 PySpark 中删除仅包含空值的列,可以先使用 count(when(col(c).isNull(), c)) 计算每列的空值数量,然后识别空值计数等于 DataFrame 总行数的列,最后使用 .drop() 方法删除这些列。

如何在 PySpark 中按条件删除列?

使用 df.select([col for col in df.columns if condition])。

Maria Eugenia Inzaugarat

作者

Maria Eugenia Inzaugarat

主题