首页 > 解决方案 > 在explode“子查询”中有效地插入when语句

问题描述

我有以下列命名data,它是具有多列的数据框的一部分:

[{"country": "FR", "createdAt": "Mon, 07 Dec 20 16:35:10 +0000", "id": 1, "stuff": ["a"]}, {"country": "UK", "createdAt": "Mon, 07 Dec 20 16:35:10 +0000", "id": 2, "stuff": ["a", "b"]}, {"country": "DE", "createdAt": "Mon, 07 Dec 20 16:35:10 +0000", "id": 3, "stuff": ["a", "b", "c"]}, {"country": "IT", "createdAt": "Mon, 07 Dec 20 16:35:10 +0000", "id": 4, "stuff": ["b"]}]

我想分解这个名为的列data,使其具有一个数据框,其中包含每个键值对的列。还有一个带有stuff键的嵌套数组,我想用条件语句将其展平。

我有以下一组运行正常的命令:

#reading api response
df = spark.read.json(sc.parallelize([json.dumps(response)]))
#first call
df = df.withColumn("data", explode("data")).select(
  col("data")["country"].alias('country'),col("data")["createdAt"].alias('creation'), col("data")["stuff"].alias('stuff'))
#second call
df = df.withColumn("stuff", when(array_contains(df.stuff, "a"),"a")  
                       .otherwise("Other"))
display(df)  

但是我想知道是否可以在带有该语句的“第一次调用”中插入WithColumn带有该方法的第二条语句。我觉得不得不三次调用 df 有点多余。array_containsexplode

标签: apache-sparkpysparkapache-spark-sql

解决方案


不可能将第二个withColumn语句放在第一个调用中,因为stuffcolumn 在数组列内,所以没有办法避免这两个步骤(根据我对 Spark 的了解)。

要减少方法调用,您可以这样做:

df = (df
      .selectExpr('inline(data)')
      .select("country", 
              col("createdAt").alias("creation"), 
              "id", 
              when(array_contains("stuff", "a"), "a").otherwise("Other").alias("stuff")))

为避免select再次调用:

df = (df
      .selectExpr('inline(data)')
      .withColumnRenamed("createdAt", "creation")
      .withColumn("stuff", when(array_contains("stuff", "a"), "a").otherwise("Other").alias("stuff")))

在引擎盖下,两个选项都将执行相同的物理计划和执行


推荐阅读