我有一个包含4个字段的数据框,如下所述:
Field1 , Field2 , Field3 , Field4
我在以下字段中有值:
A1 , B1 , C1 , D1
A2 , B2,B3 , C2,C3 , D2,D3
A1 , B4,B5,B6 , C4,C5,C6 , D4,D5,D6
我必须将其转换为以下格式:
A1 , B1 , C1 , D1
A2 , B2 , C2 , D2
A2 , B3 , C3 , D3
A1 , B4 , C4 , D4
A1 , B5 , C5 , D5
A1 , B6 , C6 , D6
基本上我必须在多列中拆分逗号分隔值,并根据相同顺序的值形成新行。
您可以将所有类型视为字符串类型。您能否建议我根据新值进行拆分和形成新行的方法。
我可以看到一个类似于下面的问题:
如何在Spark中嵌套数据框
但是这个问题不同,因为在这种情况下我必须考虑拆分多个列,并且值不应重复。
答案 0 :(得分:3)
您可以将DataFrame
转换为Dataset[(String, String, String, String)]
和flatMap
:
import scala.util.Try
val df = Seq(
("A1", "B1", "C1", "D1"),
("A2", "B2,B3", "C2,C3", "D2,D3"),
("A1", "B4,B5,B6", "C4,C5,C6", "D4,D5,D6")
).toDF("x1", "x2", "x3", "x4")
// A simple sequence of expressions which allows us to flatten the results
val exprs = (0 until df.columns.size).map(i => $"value".getItem(i))
df.select($"x1", array($"x2", $"x3", $"x4")).as[(String, Seq[String])].flatMap {
case (x1, xs) =>
Try(xs.map(_.split(",")).transpose).map(_.map("x" +: _)).getOrElse(Seq())
}.toDF.select(exprs:_*)
// +--------+--------+--------+--------+
// |value[0]|value[1]|value[2]|value[3]|
// +--------+--------+--------+--------+
// | A1| B1| C1| D1|
// | A2| B2| C2| D2|
// | A2| B3| C3| D3|
// | A1| B4| C4| D4|
// | A1| B5| C5| D5|
// | A1| B6| C6| D6|
// +--------+--------+--------+--------+
或使用UDF:
val splitRow = udf((xs: Seq[String]) =>
Try(xs.map(_.split(",")).transpose).toOption)
// Same as before but we exclude the first column
val exprs = (0 until df.columns.size - 1).map(i => $"xs".getItem(i))
df
.withColumn("xs", explode(splitRow(array($"x2", $"x3", $"x4"))))
.select($"x1" +: exprs: _*)
答案 1 :(得分:0)
您可以使用posexplode快速解决此问题。请参阅http://allabouthadoop.net/hive-lateral-view-explode-vs-posexplode/ 因此,您的代码将如下所示:
{
id: 2,
title: 'testevent',
start: new Date(2020, 4, 29),
end: new Date(2020, 5, 26),
},