【问题标题】:How to apply a filter to a section of a Pyspark dataframe如何将过滤器应用于 Pyspark 数据框的一部分
【发布时间】:2021-09-17 09:52:55
【问题描述】:

我有一个 PySpark 数据框 df,如下所示:

+---------+----------+--------+-----+------+------+
|firstname|middlename|lastname|id   |gender|salary|
+---------+----------+--------+-----+------+------+
|James    |          |Smith   |36636|M     |3000  |
|Michael  |Rose      |        |40288|M     |4000  |
|Robert   |          |Williams|42114|M     |4000  |
|Maria    |Anne      |Jones   |39192|F     |4000  |
|Jen      |Mary      |Brown   |30001|F     |2000  |
+---------+----------+--------+-----+------+------+

我只需要对 gender = M 应用 id > 4000 过滤器,并保留所有 gender = F。因此,最终的数据框应如下所示:

 +---------+----------+--------+-----+------+------+
|firstname|middlename|lastname|id   |gender|salary|
+---------+----------+--------+-----+------+------+
|Michael  |Rose      |        |40288|M     |4000  |
|Robert   |          |Williams|42114|M     |4000  |
|Maria    |Anne      |Jones   |39192|F     |4000  |
|Jen      |Mary      |Brown   |30001|F     |2000  |
+---------+----------+--------+-----+------+------+

我能想到的唯一方法是:

df_temp1 = df.filter(df.gender == 'F')
df_temp2 = df.where(df.gender == 'M').filter(df.id > 4000)
df = df_temp1.union(df_temp2)

这是最有效的方法吗?我是 Spark 的新手,因此不胜感激!

【问题讨论】:

  • 欢迎来到 SO。 df.filter("(gender == 'M' and id > 40000) or gender == 'F'") 有帮助吗?
  • 虽然维尔纳的回答是完美而准确的。我宁愿建议使用您在 Question 中提到的相同内容,至少它更具可读性。因为 Spark 可能最终会做同样的工作/最终会使用 werner 由于 Catalyst 优化而编写的代码。不会有任何性能提升。
  • 请使用 filter() 查看下面的答案,如果这对您有帮助,请告诉我们 - 如果您能帮助接受和支持,我们将不胜感激

标签: python-3.x filter pyspark apache-spark-sql


【解决方案1】:

这应该可以解决问题。 wherefilter 的别名。

>>> df.show()
+-------+------+-----+
|   name|gender|   id|
+-------+------+-----+
|  James|     M|36636|
|Michael|     M|40288|
| Robert|     F|42114|
|  Maria|     F|39192|
|    Jen|     F|30001|
+-------+------+-----+

>>> df.where(''' (gender == 'M' and id > 40000) OR gender == 'F' ''').show()
+-------+------+-----+
|   name|gender|   id|
+-------+------+-----+
|Michael|     M|40288|
| Robert|     F|42114|
|  Maria|     F|39192|
|    Jen|     F|30001|
+-------+------+-----+

【讨论】:

    【解决方案2】:

    同时使用条件 OR

    **

    df = spark.createDataFrame([(36636,"M"),(40288,"M"),(42114,"M"),(39192,"F"),(30001,"F")],["id","gender"])
    df = df.filter(((F.col("id") > 40000) & (F.col("gender") == F.lit("M"))) | (F.col("gender") == F.lit("F")))
    df.show()
    

    ** 输出

    +-----+------+
    |   id|gender|
    +-----+------+
    |40288|     M|
    |42114|     M|
    |39192|     F|
    |30001|     F|
    +-----+------+
    

    【讨论】:

    • 谢谢!你能告诉我 .lit() 是做什么的吗?
    • PySpark SQL 函数 lit() 和 typedLit() 用于通过分配文字或常量值向 DataFrame 添加新列。这两个函数都返回 Column 类型作为返回......所以,假设在这里你需要与一些字符串进行比较 - 所以在这种情况下用 lit() 包装它
    • 您能否接受并支持我的回答 - 这有帮助:)
    猜你喜欢
    • 2020-08-16
    • 2013-01-02
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 2019-06-18
    • 1970-01-01
    • 2021-05-02
    相关资源
    最近更新 更多