我正在尝试使用Spark Scala为每个日期组添加一个ID。
例如,如果输入为:
date
2019-01-29
2019-01-29
2019-07-31
2019-01-29
2019-07-31
输出为:
id, date
ABC1, 2019-01-29
ABC1, 2019-01-29
ABC1, 2019-01-29
ABC2, 2019-07-31
ABC2, 2019-07-31
有人可以帮我吗?
我成功地为每个分区添加了顺序行号,但是我希望为每个分区提供一个恒定值。
df.withColumn(lineNumColName, row_number().over(Window.partitionBy(partitionByCol).orderBy(orderByCol))).repartition(1).orderBy(orderByCol, lineNumColName)
答案 0 :(得分:2)
选项1(小型数据集):
如果数据集不大,则可以使用Window和density_rank,如下所示:
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions.{concat,lit, dense_rank}
val df = Seq(("2019-01-29"),
("2019-01-29"),
("2019-07-31"),
("2019-01-29"),
("2019-07-31")).toDF("date")
val w = Window.orderBy($"date")
val d_rank = dense_rank().over(w)
df.withColumn("id", concat(lit("ABC"), d_rank)).show(false)
输出:
+----------+----+
|date |id |
+----------+----+
|2019-01-29|ABC1|
|2019-01-29|ABC1|
|2019-01-29|ABC1|
|2019-07-31|ABC2|
|2019-07-31|ABC2|
+----------+----+
由于我们没有为partitionBy
部分指定任何值,因此将仅使用一个分区,因此效率很低。
选项2(大型数据集):
一种更有效的方法是使用zipWithIndex
函数将ID分配给大型数据集:
val df_d = df.distinct.rdd.zipWithIndex().map{ r => (r._1.getString(0), r._2 + 1) }.toDF("date", "id")
df_d.show
// Output:
+----------+---+
| date| id|
+----------+---+
|2019-01-29| 1|
|2019-07-31| 2|
+----------+---+
首先,我们使用distinct
获得数据帧的唯一值,然后调用zipWithIndex
为每个日期记录创建唯一的ID。
最后我们加入了两个数据集:
df.join(df_d, Seq("date"))
.withColumn("id", concat(lit("ABC"), $"id"))
.show
// Output:
+----------+----+
| date| id|
+----------+----+
|2019-01-29|ABC1|
|2019-01-29|ABC1|
|2019-01-29|ABC1|
|2019-07-31|ABC2|
|2019-07-31|ABC2|
+----------+----+