Apache spark 如何通过数据集循环创建摘要数据集

Apache spark 如何通过数据集循环创建摘要数据集,apache-spark,spark-dataframe,Apache Spark,Spark Dataframe,我刚开始学习和使用Spark,现在面临一个问题。任何建议或暗示都将不胜感激 基本上,我有一个数据集,包含不同用户的所有类型的事件,如AppLaunch、GameStart、GameEnd等。我想创建每个用户每次启动应用程序时的动作摘要 例如:我有以下数据集: UserId |事件类型|时间|游戏类型|事件Id | 11111 | AppLauch | 11:01:53 | null | 101 | 11111 |游戏开始| 11:01:59 |拼图| 102 | 11111 | GameEnd

我刚开始学习和使用Spark,现在面临一个问题。任何建议或暗示都将不胜感激

基本上,我有一个数据集,包含不同用户的所有类型的事件,如AppLaunch、GameStart、GameEnd等。我想创建每个用户每次启动应用程序时的动作摘要

例如:我有以下数据集:
UserId |事件类型|时间|游戏类型|事件Id |

11111 | AppLauch | 11:01:53 | null | 101 |

11111 |游戏开始| 11:01:59 |拼图| 102 |

11111 | GameEnd | 11:05:31 |拼图| 103 |

11111 |游戏开始| 11:05:58 | Word | 104 |

11111 | GameEnd | 11:09:13 | Word | 105 |

11111 | AppEnd | 11:09:24 | null | 106 |

11111 | AppLauch | 12:03:43 | null | 107 |

22222 | AppLauch | 12:03:52 | null | 108 |

22222 |游戏开始| 12:03:59 |拼图| 109 |

11111 |游戏开始| 12:04:01 |拼图| 110 |

22222 | GameEnd | 12:06:11 |拼图| 111 |

11111 | GameEnd | 12:06:13 |拼图| 112 |

11111 | AppEnd | 12:06:23 | null | 113 |

22222 | AppEnd | 12:06:33 | null | 114 |

我想要的是一个类似这样的数据集:
EventId | USerId |事件类型|时间|首次玩过的游戏|最后玩过的游戏|

101 | 11111 | AppLauch | 11:01:53 |拼图|单词|

107 | 11111 | AppLauch | 12:03:43 |拼图|拼图|

108 | 22222 | AppLauch | 12:03:52 |拼图|拼图|

只需要知道第一次玩的游戏和最后一次玩的游戏,即使一个应用程序发布中玩了3个以上的游戏

我最初的想法是根据用户Id和时间窗口(AppLaunch to AppEnd)对它们进行分组,然后找到一种方法来扫描数据集,如果有一个gameStart事件并且它落在任何窗口中,它将是第一个玩过的游戏,在AppEnd之前的最后一个gameStart事件将是最后一个玩过的游戏。但我没有找到一个方法来实现这一点

任何提示/建议都很好


谢谢

我认为这可以通过使用窗口函数和如下聚合来解决:

df
   // enumerate AppLaunches 
   .withColumn("AppLauchNr", sum(when($"EventType" === "AppLauch", 1)).over(Window.partitionBy($"UserId").orderBy($"Time".asc)))
   // get first last game per AppLaunch
   .withColumn("firstGamePlayed", first($"GameType", true).over(Window.partitionBy($"UserId", $"AppLauchNr").orderBy($"Time".asc)))
   .withColumn("lastGamePlayed", first($"GameType", true).over(Window.partitionBy($"UserId", $"AppLauchNr").orderBy($"Time".desc)))
    // now aggregate
   .groupBy($"AppLauchNr")
   .agg(
        first($"UserId").as("UserId"),
        min($"EventId").as("EventId"),
        lit("AppLauch").as("EventType"), // this is always AppLauch
        min($"Time").as("Time"),
        first($"firstGamePlayed", true).as("firstGamePlayed"),
        first($"lastGamePlayed", true).as("lastGamePlayed")
   )
  .drop($"AppLauchNr")
第一个和最后一个游戏也可以使用
orderBy().groupBy()
而不是窗口函数来确定,但我仍然不确定spark是否会在聚合过程中保留顺序(文档中未提及这一点,请参见中的示例和讨论)


首先使用窗口函数获取第一个和最后一个游戏,然后groupBy将每个userId减少到1行,但groupBy userId不知道它是什么事件吗?
 df
   .withColumn("AppLauchNr", sum(when($"EventType" === "AppLauch", 1)).over(Window.partitionBy($"UserId").orderBy($"Time".asc)))
   .orderBy($"UserId",$"AppLauchNr",$"Time")
   .groupBy($"UserId",$"AppLauchNr")
   .agg(
        first($"EventId").as("EventId"),
        first($"EventType").as("EventType"),
        first($"Time").as("Time"),
        first($"GameType", true).as("firstGamePlayed"),
        last($"GameType", true).as("lastGamePlayed")
   )
   .drop($"AppLauchNr")