-2

I have a dataframe that looks like this:

+--------+-----+--------------------+
|     uid|  iid|               color|
+--------+-----+--------------------+
|41344966| 1305|                 red| 
|41344966| 1305|               green|

I want to get to this as efficiently as possible:

+--------+--------------------+
|     uid|     recommendations|
+--------+--------------------+
|41344966|      [[2174, red...|
|41345063|    [[2174, green...|
|41346177|   [[2996, orange...|
|41349171|   [[2174, purple...|

res98: org.apache.spark.sql.Dataset[userRecs] = [uid: int, recommendations: array<struct<iid:int,color:string>>]

So I want to group records by uid into an array of objects. Each object is a class with parameters iid and color.

case class itemData (iid: Int, color: String)

case class userRecs (uid: Int, recommendations: Array[itemData])

Seth Tisue
  • 29,985
  • 11
  • 82
  • 149
Ollie
  • 624
  • 8
  • 27

1 Answers1

4

Does this do what you want?

scala> case class itemData (iid: Int, color: String)
defined class itemData

scala> case class userRecs (uid: Int, recommendations: Array[itemData])
defined class userRecs

scala> val df = spark.createDataset(Seq(
    (41344966,1305,"red"),
    (41344966,1305,"green"),
    (41344966,2174,"red"),
    (41345063,2174,"green"),
    (41346177,2996,"orange"),
    (41349171,2174,"purple")
)).toDF("uid", "iid", "color")
df: org.apache.spark.sql.DataFrame = [uid: int, iid: int ... 1 more field]

scala> (df.select($"uid", struct($"iid",$"color").as("itemData"))
        .groupBy("uid")
        .agg(collect_list("itemData").as("recommendations"))
        .as[userRecs]
        .show())
+--------+--------------------+
|     uid|     recommendations|
+--------+--------------------+
|41344966|[[1305, red], [13...|
|41345063|     [[2174, green]]|
|41346177|    [[2996, orange]]|
|41349171|    [[2174, purple]]|
+--------+--------------------+
Travis Hegner
  • 2,465
  • 1
  • 12
  • 11