在PySpark Dataframe 中,如何从一个结构体数组转换到每个结构体的第一个元素的数组?
下面的例子会让我们更清楚地了解这一点。
scoresheet = spark.createDataFrame([("Alice", [("Math",100),("English",80)]),("Bob", [("Math", 90)]),("Charlie", [])],["name","scores"])
上面定义的模式和 Dataframe 如下所示:
root
|-- name: string (nullable = true)
|-- scores: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- _1: string (nullable = true)
| | |-- _2: long (nullable = true)
+-------+--------------------------+
|name |scores |
+-------+--------------------------+
|Alice |[[Math,100], [English,80]]|
|Bob |[[Math,90]] |
|Charlie|[] |
+-------+--------------------------+
你可以看到,每个学生的科目分数都包含在一个(Subject,Marks)
类型的有序结构体中,每个学生的科目数不是常数,可能是零。
接下来,我将生成一个新的 Dataframe ,其中只包含每个学生的主题,而不包含分数。它应该为没有主题的学生生成一个空数组。简而言之,它应该如下所示:
+-------+---------------+
|name |scores |
+-------+---------------+
|Alice |[Math, English]|
|Bob |[Math] |
|Charlie|[] |
+-------+---------------+
请注意,行数与前面相同;所以我不能使用explode,除非我在之后重新组合,这在计算上效率很低。
3条答案
按热度按时间voj3qocg1#
最好的方法是udf:
06odsfpq2#
作为参考,下面是包含分解、分组依据和聚合的版本。
由于这是在PySpark中完成的,所以在某些情况下,如果它比UDF版本快,我不会感到惊讶,但我没有做任何分析。左连接是为了确保没有结果的学生不会在最终结果中被丢弃。
2ic8powd3#
这将获得预期的结果:
输出为:
_1
是数组元素的结构字段名,如记分表架构所示:作为一般规则,
.select("<column_name>.<field_name>")
从结构体或结构体数组中提取字段。由于DataFrame构造中未提供架构,因此
scores
列中得字段获得了自动生成得名称_1
与_2
.若要提高可读性,可以将它们指定为subject
与mark
,然后使用scores.subject
与scores.mark
访问它们: