PySpark如何遍历DataFrame并删除含指定Country值的行
如何删除DataFrame中含
country: "China"的行并写入外部存储 先看你提供的DataFrame:
| Column A | Column B |
|---|---|
| Hello | [{id: 1000, abbreviatedId: 1, name: "John", planet: "Earth", solarsystem: "Milky Way", universe: "this one", continent: {id: 33, country: "China", Capital: "Bejing"}, otherId: 400, language: "Cantonese", species: 23409, creature: "Human"}] |
| Bye | [{id: 2000, abbreviatedId: 2, name: "James", planet: "Earth", solarsystem: "Milky Way", universe: "this one", continent: {id: 33, country: "Russia", Capital: "Moscow"}, otherId: 500, language: "Russian", species: 12308, creature: "Human"}] |
你尝试的两段代码都存在问题:
- 第一段里
df.select(array_contains(...))返回的是DataFrame对象,不是布尔值,直接和True比较完全不成立,逻辑根本走不通。 - 第二段用
rdd.collect()遍历行,然后调用df.drop(row),但Spark的DataFrame是不可变的,drop不会修改原DataFrame,而且这种把全量数据拉到本地遍历的方式完全违背Spark分布式计算的初衷,效率极低,逻辑也不对。
正确解法
因为Column B是数组嵌套结构体,直接用Spark的分布式过滤操作即可,不用遍历行:
方法1:用exists函数(推荐,语义更清晰)
from pyspark.sql import functions as F # 过滤掉Column B中存在country为China的行 filtered_df = df.filter(~F.exists(F.col("Column B"), lambda elem: elem["continent"]["country"] == "China")) # 写入Delta格式存储 filtered_df.write.format("delta").mode("overwrite").save("file://path/")
方法2:用transform+array_contains
先把Column B数组里每个元素的continent.country提取出来,再检查是否包含"China":
from pyspark.sql import functions as F filtered_df = df.filter( ~F.array_contains( F.transform(F.col("Column B"), lambda elem: elem["continent"]["country"]), "China" ) ) filtered_df.write.format("delta").mode("overwrite").save("file://path/")
说明
~符号表示取反,也就是保留那些数组中没有country为China的行。- Spark的
filter操作是分布式执行的,比你遍历行的方式效率高得多,完全符合Spark的设计逻辑。
内容的提问来源于stack exchange,提问作者Alyssa
相关产品推荐
相关产品推荐

