如何基于定界符

时间:2019-08-05 07:29:12

标签: apache-spark

输入

Column1     column2.        column3
(1,2)       (xyz,abc).      (123,456)

输出应为

Column1  column2     column3
1.       Xyz.        123
2.       Abc.        456

我需要在数据帧中拆分数据。由于每列的第一个元素应该排成一行,第二列的元素排成第二列,依此类推,该数据的元素将被拆分并随后成为另一行。

1 个答案:

答案 0 :(得分:1)

如果您使用的是最新版本的Spark,arrays_zip将帮助您完成所需的工作:

// define test dataset
val df = spark.createDataset(List(("(1,2)","(xyz,abc)","(123,456)")))
    .toDF("Column1","Column2","Column3") 

df.show
+-------+---------+---------+
|Column1|  Column2|  Column3|
+-------+---------+---------+
|  (1,2)|(xyz,abc)|(123,456)|
+-------+---------+---------+

使用此数据集,您可以将所有定界的文本值拆分为数组:

val reshape_cols = df.columns
    .map(c => split(regexp_replace(col(c),"[()]",""),",").as(c))
val reshaped_df = df.select(reshape_cols:_*)

reshaped_df.show
+-------+----------+----------+
|Column1|   Column2|   Column3|
+-------+----------+----------+
| [1, 2]|[xyz, abc]|[123, 456]|
+-------+----------+----------+

现在有了数组,您可以使用arrays_zip来生成struct类型数组的单列

val zipped_df = reshaped_df
    .select(arrays_zip(reshaped_df.columns.map(col):_*).as("value")) 

zipped_df.show(false)
+------------------------------+
|value                         |
+------------------------------+
|[[1, xyz, 123], [2, abc, 456]]|
+------------------------------+

现在您有了一个结构数组,可以使用explode将您的单行转换为多行:

val final_df = zipped_df
    .select(explode('value).as("s"))
    .select(df.columns.map(c => 's(c).as(c)):_*)

final_df.show
+-------+-------+-------+
|Column1|Column2|Column3|
+-------+-------+-------+
|      1|    xyz|    123|
|      2|    abc|    456|
+-------+-------+-------+