在pyspark数据帧

时间:2017-05-01 17:55:01

标签: pyspark spark-dataframe pyspark-sql

是否有类似于collect_list或collect_set的函数将一列映射聚合到(分组)pyspark数据帧中的单个映射中?例如,此函数可能具有以下行为:

>>>df.show()

+--+---------------------------------+
|id|                             map |
+--+---------------------------------+
| 1|                    Map(k1 -> v1)|
| 1|                    Map(k2 -> v2)|
| 1|                    Map(k3 -> v3)|
| 2|                    Map(k5 -> v5)|
| 3|                    Map(k6 -> v6)|
| 3|                    Map(k7 -> v7)|
+--+---------------------------------+

>>>df.groupBy('id').agg(collect_map('map')).show()

+--+----------------------------------+
|id|                 collect_map(map) |
+--+----------------------------------+
| 1| Map(k1 -> v1, k2 -> v2, k3 -> v3)|
| 2|                     Map(k5 -> v5)|
| 3|           Map(k6 -> v6, k7 -> v7)|
+--+----------------------------------+

使用其他collect_ aggregations和udf之一生成所需结果可能不会太难,但似乎这样的事情应该已经存在。

3 个答案:

答案 0 :(得分:3)

我知道在其他人有机会回答之前提供自己问题的答案可能是不好的形式,但是如果有人正在寻找基于udf的版本,这里有一个可能的答案。

from pyspark.sql.functions import udf,collect_list
from pyspark.sql.types import MapType,StringType

combineMap=udf(lambda maps: {key:f[key] for f in maps for key in f},
               MapType(StringType(),StringType()))

df.groupBy('id')\
  .agg(collect_list('map')\
  .alias('maps'))\
  .select('id',combineMap('maps').alias('combined_map')).show()

答案 1 :(得分:0)

是pyspark版本中的map_concat> = 2.4

答案 2 :(得分:0)

使用concat_map的建议解决方案无效,并且该解决方案不使用UDF。
对于spark> = 2.4

(df
.groupBy(f.col('id'))
.agg(f.collect_list(f.col('map')).alias('maps'), 
.select('id',
        f.expr('aggregate(slice(maps, 2, size(maps)), maps[0], (acc, element) -> map_concat(acc, element))').alias('mapsConcatenated')
        )
)

collect_list忽略空值,因此在聚合函数中使用map_concat时无需担心它们。