有人知道在Scala中基于两列范围将行爆炸成多行的好方法吗?
例如,对于输入数据框:
start_ip_int | end_ip_int | country | city
100 | 105 | USA | Boston
预期的输出数据帧为:
start_ip_int | end_ip_int | country | city | ip
100 | 105 | USA | Boston | 100
100 | 105 | USA | Boston | 101
100 | 105 | USA | Boston | 102
100 | 105 | USA | Boston | 103
100 | 105 | USA | Boston | 104
100 | 105 | USA | Boston | 105
因此,根据列start_ip_int
和end_ip_int
的范围,将一行分为6行。
答案 0 :(得分:3)
如果您使用的是Spark 2.4+
,请使用带有IP整数范围的sequence
作为参数来生成ArrayType
列,然后explode
对其进行输入:>
val df = Seq((100, 105, "USA", "Boston")).
toDF("start_ip_int", "end_ip_int", "country", "city")
df.withColumn("ip", explode(sequence($"start_ip_int", $"end_ip_int"))).show
// +------------+----------+-------+------+---+
// |start_ip_int|end_ip_int|country| city| ip|
// +------------+----------+-------+------+---+
// | 100| 105| USA|Boston|100|
// | 100| 105| USA|Boston|101|
// | 100| 105| USA|Boston|102|
// | 100| 105| USA|Boston|103|
// | 100| 105| USA|Boston|104|
// | 100| 105| USA|Boston|105|
// +------------+----------+-------+------+---+
对于较旧的Spark版本,请考虑创建一个简单的UDF来模仿sequence
函数:
val rangeSequence = udf{ (lower: Int, upper: Int) =>
Seq.iterate(lower, upper - lower + 1)(_ + 1)
}
// Applying the UDF, followed by `explode`
df.withColumn("ip", explode(rangeSequence($"start_ip_int", $"end_ip_int")))