Как собрать карту после группировки в датафрейме Pyspark? - PullRequest
1 голос
/ 05 ноября 2019

У меня есть такой фрейм данных pyspark:

|  id  |  time  |  cat  |
-------------------------
   1       t1       a
   1       t2       b
   2       t3       b
   2       t4       c
   2       t5       b
   3       t6       a
   3       t7       a
   3       t8       a

Теперь я хочу сгруппировать их по "id" и объединить их в карту следующим образом:

|   id  |       cat       |
---------------------------
|   1   |  a -> 1, b -> 1 |
|   2   |  b -> 2, c -> 1 |
|   3   |  a -> 3         |

Iдумаю, мы можем использовать функцию pyspark sql collect_list , чтобы собрать их как список, а затем я мог бы применить некоторую функцию UDF, чтобы превратить список в dict. Но есть ли другой (более короткий или более эффективный) способ сделать это?

Ответы [ 2 ]

2 голосов
/ 05 ноября 2019

Вы можете использовать эту функцию с pyspark.sql.functions.map_from_entries, если мы считаем, что ваш фрейм данных является df, вы должны сделать это:

import pyspark.sql.functions as F

df1 = df.groupby("id", "cat").count()
df2 = df1.groupby("id")\
         .agg(F.map_from_entries(F.collect_list(F.struct("cat","count"))).alias("cat"))
0 голосов
/ 05 ноября 2019

Вот как я это сделал.

Код

import pyspark.sql.functions as F
from pyspark.sql.types import StringType

df = spark.createDataFrame([(1,'t1','a'),(1,'t2','b'),(2,'t3','b'),(2,'t4','c'),(2,'t5','b'),\
(3,'t6','a'),(3,'t7','a'),(3,'t8','a')],\
('id','time','cat'))

(df.groupBy(['id', 'cat'])
   .agg(F.count(F.col('cat')).cast(StringType()).alias('counted'))
   .select(['id', F.concat_ws('->', F.col('cat'), F.col('counted')).alias('arrowed')])
   .groupBy('id')
   .agg(F.collect_list('arrowed'))
   .show()
)

Вывод

+-------+---------------------+
|     id|collect_list(arrowed)|
+-------+---------------------+
|   1   |    [a -> 1, b -> 1] |
|   3   |            [a -> 3] |
|   2   |    [b -> 2, c -> 1] |
+-------+---------------------+

Редактировать

(df.groupBy(['id', 'cat'])
   .count()
   .select(['id',F.create_map('cat', 'count').alias('map')])
   .groupBy('id')
   .agg(F.collect_list('map').alias('cat'))
   .show()
)

#+---+--------------------+
#| id|                 cat|
#+---+--------------------+
#|  1|[[a -> 1], [b -> 1]]|
#|  3|          [[a -> 3]]|
#|  2|[[b -> 2], [c -> 1]]|
#+---+--------------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...