【发布时间】:2018-03-04 08:58:47
【问题描述】:
我有一个以下格式的 Apache Spark 数据框
| ID | groupId | phaseName |
|----|-----------|-----------|
| 10 | someHash1 | PhaseA |
| 11 | someHash1 | PhaseB |
| 12 | someHash1 | PhaseB |
| 13 | someHash2 | PhaseX |
| 14 | someHash2 | PhaseY |
每一行代表一个过程中发生的一个阶段,该过程由多个这些阶段组成。 ID 列表示相的顺序,groupId 列显示哪些相属于一起。
我想向数据框添加一个新列:previousPhaseName。此列应指明同一程序的先前不同阶段。进程的第一阶段(具有最小 ID 的阶段)将 null 作为前一阶段。当一个阶段出现两次或更多次时,第二次(第三次...)出现将具有相同的 previousPhaseName 例如:
df =
| ID | groupId | phaseName | prevPhaseName |
|----|-----------|-----------|---------------|
| 10 | someHash1 | PhaseA | null |
| 11 | someHash1 | PhaseB | PhaseA |
| 12 | someHash1 | PhaseB | PhaseA |
| 13 | someHash2 | PhaseX | null |
| 14 | someHash2 | PhaseY | PhaseX |
我不确定如何实现这一点。我的第一种方法是:
- 创建第二个空数据框 df2
- 对于 df 中的每一行:
找到 groupId = row.groupId, ID - 将此行添加到 df2
- 加入 df1 和 df2
使用窗口函数的部分解决方案
我用Window Functions聚合了上一个阶段的名称,该组中当前阶段以前出现的次数(不一定是一行)以及当前和上一个阶段名称是否相等的信息:
WindowSpec windowSpecPrev = Window
.partitionBy(df.col("groupId"))
.orderBy(df.col("ID"));
WindowSpec windowSpecCount = Window
.partitionBy(df.col("groupId"), df.col("phaseName"))
.orderBy(df.col("ID"))
.rowsBetween(Long.MIN_VALUE, 0);
df
.withColumn("prevPhase", functions.lag("phaseName", 1).over(windowSpecPrev))
.withColumn("phaseCount", functions.count("phaseId").over(windowSpecCount))
.withColumn("prevSame", when(col("prevPhase").equalTo(col("phaseName")),1).otherwise(0))
df =
| ID | groupId | phaseName | prevPhase | phaseCount | prevSame |
|----|-----------|-----------|-------------|------------|----------|
| 10 | someHash1 | PhaseA | null | 1 | 0 |
| 11 | someHash1 | PhaseB | PhaseA | 1 | 0 |
| 12 | someHash1 | PhaseB | PhaseB | 2 | 1 |
| 13 | someHash2 | PhaseX | null | 1 | 0 |
| 14 | someHash2 | PhaseY | PhaseX | 1 | 0 |
这仍然不是我想要达到的目标,但现在已经足够了
进一步的想法
为了获得前一个不同阶段的名称,我看到了三种我没有彻底调查过的可能性:
- 实现一个自己的
lag函数,它不使用偏移量,而是递归检查前一行,直到找到与给定行不同的值。 (虽然我认为在 Spark SQL 中无法使用自己的分析窗口函数) - 想办法根据
phaseCount的值动态设置lag函数的偏移量。 (如果之前出现的相同 phaseName 没有出现在单个序列中,这可能会失败) - 在存储第一个给定输入的 ID 和 phaseName 的窗口上使用
UserDefinedAggregateFunction,并寻找具有不同 phaseName 的最高 ID。
【问题讨论】:
标签: java sql apache-spark apache-spark-sql gaps-and-islands