【问题标题】:Remove nested column in pyspark删除 pyspark 中的嵌套列
【发布时间】:2020-06-14 21:22:52
【问题描述】:

我有一个带有列结果的 pyspark 数据框。在结果列中,我想删除该列 “属性”。 数据框的架构是:(结果中有更多列,但为方便起见,我没有显示它们,因为架构很大)

 |-- results: struct (nullable = true)
 |    |-- l: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- m: struct (nullable = true)
 |    |    |    |    |-- Attributes: struct (nullable = true)
 |    |    |    |    |    |-- m: struct (nullable = true)
 |    |    |    |    |    |    |-- Score: struct (nullable = true)
 |    |    |    |    |    |    |    |-- n: string (nullable = true)
 |    |    |    |    |-- OtherInfo: struct (nullable = true)
 |    |    |    |    |    |-- l: array (nullable = true)
 |    |    |    |    |    |    |-- element: struct (containsNull = true)
 |    |    |    |    |    |    |    |-- m: struct (nullable = true)
 |    |    |    |    |    |    |    |    |-- Name: string (nullable = true)

如何在 pyspark 中没有 udf 的情况下执行此操作?

编辑:

一行是:

{
   "results" : {
        "l" : [
            {
              "m":{
                  "Attributes" : {
                      "m" : {
                           "Score" : {"n" : "85"}
                       }
                  },
                   "OtherInfo":{
                      "l" : [
                           {
                             "m" : {
                               "Name" : {"john"}
                             }
                          },
                          {
                             "m" : {
                                "Name" : "Cena"}
                          }
                       ]
                   }
             }
           }   
         ]
    }
}

【问题讨论】:

  • 你能提供至少 10 行的这个数据集吗?
  • 我提供了一行。我认为 1 行就足够了。

标签: python apache-spark pyspark apache-spark-sql pyspark-dataframes


【解决方案1】:

要从结构类型中删除字段,您必须创建一个包含所有元素的新结构,但要从原始结构中删除的元素除外。

这里,由于results 下的字段l 是一个数组,您可以使用transform 函数(Spark 2.4+)来更新它的所有结构元素,如下所示:

from pyspark.sql.functions import struct, expr


t_expr = "transform(results.l, x -> struct(struct(x.m.OtherInfo as OtherInfo) as m))"
df = df.withColumn("results", struct(expr(t_expr).alias("l")))

对于数组中的每个元素x,我们创建仅包含x.m.OtherInfo 字段的新结构。

df.printSchema()

#root
# |-- results: struct (nullable = false)
# |    |-- l: array (nullable = true)
# |    |    |-- element: struct (containsNull = false)
# |    |    |    |-- m: struct (nullable = false)
# |    |    |    |    |-- OtherInfo: struct (nullable = true)
# |    |    |    |    |    |-- l: array (nullable = true)
# |    |    |    |    |    |    |-- element: struct (containsNull = true)
# |    |    |    |    |    |    |    |-- m: struct (nullable = true)
# |    |    |    |    |    |    |    |    |-- Name: string (nullable = true)

【讨论】:

  • 不错的解决方案!如果还有一个字段 otherinfo2 如何在转换中传递它
  • 只需将其添加到新结构中:struct(x.m.OtherInfo as OtherInfo, x.m.OtherInfo2 as OtherInfo2)。如果您有很多字段并且不想对它们进行硬编码,则可以从架构中获取字段名称并使用 Python 循环构建转换表达式字符串。
  • 酷。如果现在说某些项目没有其他信息(在某些情况下为空或不存在),那么这将起作用。以及如何在转换后的框架中填充其他信息?
  • @kmkhan 是的,它也应该可以工作。这些文件将是空的。
  • ParseException: "\nmismatched input 'as' Expecting {')', ','}(line 1, pos 70)\n\n== SQL ==\ntransform(results.l, x -> f.struct(f.struct(x.m.OtherInfo as OtherInfo) as m)) 我得到了这个异常。
猜你喜欢
  • 1970-01-01
  • 2021-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2015-12-20
相关资源
最近更新 更多