【问题标题】:overwrite column values using other column values based on conditions pyspark根据条件pyspark使用其他列值覆盖列值
【发布时间】:2018-06-11 11:02:10
【问题描述】:

我在pyspark 中有一个data frame,如下所示。

df.show()

+-----------+------------+-------------+
|customer_id|product_name|      country|
+-----------+------------+-------------+
|   12870946|        null|       Poland|
|     815518|       MA401|United States|
|    3138420|     WG111v2|           UK|
|    3178864|    WGR614v6|United States|
|    7456796|       XE102|United States|
|   21893468|     AGM731F|United States|
+-----------+------------+-------------+

我有另一个数据框,如下所示 df1.show()

+-----------+------------+
|customer_id|product_name|
+-----------+------------+
|   12870946|     GS748TS|
|     815518|       MA402|
|    3138420|        null|
|    3178864|    WGR614v6|
|    7456796|       XE102|
|   21893468|     AGM731F|
|       null|       AE171|
+-----------+------------+

现在我想对这些表执行fuller outer join 并更新product_name 列值,如下所示。

1) Overwrite the values in `df` using values in `df1` if there are values in `df1`.
2) if there are `null` values or `no` values in `df1` then leave the values in `df` as they are 

expected result

+-----------+------------+-------------+
|customer_id|product_name|      country|
+-----------+------------+-------------+
|   12870946|     GS748TS|       Poland|
|     815518|       MA402|United States|
|    3138420|     WG111v2|           UK|
|    3178864|    WGR614v6|United States|
|    7456796|       XE102|United States|
|   21893468|     AGM731F|United States|
|       null|       AE171|         null|
+-----------+------------+-------------+

我已经完成了如下操作

import pyspark.sql.functions as f
df2 = df.join(df1, df.customer_id == df1.customer_id, 'full_outer').select(df.customer_id, f.coalesce(df.product_name, df1.product_name).alias('product_name'), df.country)

但我得到的结果不一样

df2.show()

+-----------+------------+-------------+
|customer_id|product_name|      country|
+-----------+------------+-------------+
|   12870946|        null|       Poland|
|     815518|       MA401|United States|
|    3138420|     WG111v2|           UK|
|    3178864|    WGR614v6|United States|
|    7456796|       XE102|United States|
|   21893468|     AGM731F|United States|
|       null|       AE171|         null|
+-----------+------------+-------------+

如何获得expected result

【问题讨论】:

  • 您提供的代码对我有用。你确定你的数据框中有实际的null 值而不是字符串"null"
  • @pault 他们是nullNot null 字符串,我无法得到我想要的结果。能否请您在运行代码时提供结果?

标签: apache-spark pyspark


【解决方案1】:

您编写的代码为我生成了正确的输出,因此我无法重现您的问题。我看过其他帖子,其中在执行连接时使用别名已经解决了问题,所以这里有一个稍微修改过的代码版本,它会做同样的事情:

import pyspark.sql.functions as f

df.alias("r").join(df1.alias("l"), on="customer_id", how='full_outer')\
    .select(
        "customer_id",
        f.coalesce("r.product_name", "l.product_name").alias('product_name'),
        "country"
    )\
    .show()
#+-----------+------------+-------------+
#|customer_id|product_name|      country|
#+-----------+------------+-------------+
#|    7456796|       XE102|United States|
#|    3178864|    WGR614v6|United States|
#|       null|       AE171|         null|
#|     815518|       MA401|United States|
#|    3138420|     WG111v2|           UK|
#|   12870946|     GS748TS|       Poland|
#|   21893468|     AGM731F|United States|
#+-----------+------------+-------------+

我在运行您的代码时也得到了相同的结果(转载如下):

df.join(df1, df.customer_id == df1.customer_id, 'full_outer')\
    .select(
        df.customer_id,
        f.coalesce(df.product_name, df1.product_name).alias('product_name'),
        df.country
    )\
    .show()

我使用的是 spark 2.1 和 python 2.7.13。

【讨论】:

  • 看起来数据已损坏当我手动创建 data frames 然后运行您的代码时,我得到了想要的结果,我的代码都给了我正确的结果
【解决方案2】:

如果值不是字符串 null,你的代码就是完美的。但是查看 df2 数据框,您会得到product_name 中的值似乎是字符串 null。您必须使用 when inbuilt functionisnull inbuilt function 来检查 string null

import pyspark.sql.functions as f
df2 = df.join(df1, df.customer_id == df1.customer_id, 'full_outer')\
    .select(df.customer_id, f.when(f.isnull(df.product_name) | (df.product_name == "null"), df1.product_name).otherwise(df.product_name).alias('product_name'), df.country)
df2.show(truncate=False)

这应该给你

+-----------+------------+------------+
|customer_id|product_name|country     |
+-----------+------------+------------+
|7456796    |XE102       |UnitedStates|
|3178864    |WGR614v6    |UnitedStates|
|815518     |MA401       |UnitedStates|
|3138420    |WG111v2     |UK          |
|12870946   |GS748TS     |Poland      |
|21893468   |AGM731F     |UnitedStates|
|null       |AE171       |null        |
+-----------+------------+------------+

【讨论】:

    【解决方案3】:

    由于存在一些相互冲突的报告 - 首先只需在 df1 中使用您要使用的 df2 中的列创建一个新列,假设您的 df 具有相同的维度,或者如果不是则根据需要加入它们。然后您可以使用 SQL条件。

    from pyspark.sql import functions as F
    df1 = df1.withColumn('column', F.when(df1['column'].isNull(), df1['column']).otherwise(df1['other-column-originally-from-df2']) )
    

    【讨论】:

    • 我收到以下错误pyspark.sql.utils.AnalysisException: u'resolved attribute(s) product_name#9 missing from customer_id#11,product_name#12 in operator !Project [customer_id#11,product_name#12,CASE WHEN isnull(product_name#12) THEN product_name#9 ELSE product_name#12 AS model#13];' 我已经完成了如下df2 = df1.withColumn('model', f.when(df1['product_name'].isNull(), df['product_name']).otherwise(df1['product_name']))
    • 在处理一个 DataFrame 时不能引用另一个 DataFrame。即: df.withColumn("X1", df1[...]) 不正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 2022-12-21
    • 2020-09-17
    • 2019-02-12
    • 2019-06-06
    相关资源
    最近更新 更多