如何在Spark 2中将列拆分为多个列?

时间:2018-01-05 18:15:58

标签: scala apache-spark apache-spark-sql

我正在使用Spark 2.2.0和Scala 2.11.8将数据从HDFS读入DataFrame:

val df = spark.read.text(outputdir)
df.show()

我看到了这个结果:

+--------------------+
|               value|
+--------------------+
|(4056,{community:...|
|(56,{community:56...|
|(2056,{community:...|
+--------------------+

如果我运行df.head(),我会看到有关每行结构的更多详细信息:

[(4056,{community:1,communitySigmaTot:1020457,internalWeight:0,nodeWeight:1020457})]

我想获得以下输出:

+---------+----------+
|     id  |     value|
+---------+----------+
|4056     |1         |
|56       |56        |
|2056     |20        |
+---------+----------+

我该怎么办?我尝试使用.map(row => row.mkString(",")), 但我不知道如何提取数据。

3 个答案:

答案 0 :(得分:2)

问题是您将数据作为单个字符串列获取。问题中没有真正指定数据格式(理想情况下它会像JSON一样),但根据我们所知,我们可以使用正则表达式来提取左侧(id)和社区字段的数字:

val r = """\((\d+),\{.*community:(\d+).*\}\)"""

df.select(
    F.regexp_extract($"value", r, 1).as("id"),
    F.regexp_extract($"value", r, 2).as("community")
).show()

答案 1 :(得分:1)

一堆正则表达式应该可以提供所需的结果。

df.select(
  regexp_extract($"value", "^\\(([0-9]+),.*$", 1) as "id", 
  explode(split(regexp_extract($"value", "^\\(([0-9]+),\\{(.*)\\}\\)$", 2), ",")) as "value"
).withColumn("value", split($"value", ":")(1))

答案 2 :(得分:1)

如果您的数据始终采用以下格式

(4056,{community:1,communitySigmaTot:1020457,internalWeight:0,nodeWeight:1020457})

然后,您只需使用splitregex_replace内置函数即可获得所需的输出dataframe

import org.apache.spark.sql.functions._
df.select(regexp_replace((split(col("value"), ",")(0)), "\\(", "").as("id"), regexp_replace((split(col("value"), ",")(1)), "\\{community:", "").as("value")  ).show()

我希望答案很有帮助