如何最好地将SparkSQL Dataframe Array [String]列转换为新的[String]列

时间:2019-04-05 10:45:27

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

我是Spark的新手,我有一个包含4列的Apache SparkSQL DataFrame df,具有以下架构:

root
 |-- _id: string (nullable = false)
 |-- _title: string (nullable = false)
 |-- _published-at: date (nullable = false)
 |-- p: array (nullable = true)
 |    |-- element: string (containsNull = true)

df包含大量(一百万左右)新闻文章,每条记录的列包含:唯一ID(_id),标题(_title),发布日期(_published-at)和String数组每篇文章(p)中的 paragraphs 文本。

我现在想将“ p”列从文章段落的当前格式Array[String]转换为文章全文的融合String,其中转换是段落的简单映射元素之间用空格(“”)串联,从而在String中添加了新的第五df列。即像这样的东西:

df.withColumn(df.(col"p").map(_.mkString(" ")).alias("fullarticle"))

这不起作用。但是,这似乎是一个微不足道的问题,但是我一定错了。在Spark的functions包中,可以找到许多功能,但是似乎没有合适的功能。我必须以某种方式使用“用户定义函数”(UDF)吗?最好是避免这种情况。

可以通过以下操作将其转换为String,从而产生一个新的Dataset[String] dsFullArticles

dsFullArticles = df.select(col("p").as[Array[String]]).map(_.mkString(" ")).alias("fullarticle")

(似乎需要.as[Array[String]]来解开实际上包裹了“ p”列中每个WrappedArray元素的Array[String])。但是如何代替将dsFullArticles作为新的附加到df

此后,我还想在“全文”列中找到每篇文章的最长单词的长度,并将其作为第六列添加到df中:

// Split each article in an array of its words
val dsFullArticlesArrayOfWords = dsFullArticles.map(s => s.split(" "))
// Find number of characters of longest word in article, 0 if article is empty
val dsMaxWordLength =
  dsFullArticlesArrayOfWords.map(s => (s.map(w => w.length()) match {
    case x if x.isEmpty => 0  
    case x => x.max
  }))

上面的代码也可以正常工作,产生Dataset[int],但是,如何类似地将其作为列添加到df中呢?同样的问题在这里。当所有内容都在同一DataFrame df中时,很容易进行各种SQL选择,过滤等。

1 个答案:

答案 0 :(得分:0)

您可以使用concat_ws功能:

  

concat_ws(sep,[str | array(str)] +)-返回由Sep分隔的字符串的串联。

在您的情况下:

df.withColumn("fullarticle", concat_ws(" ",col("p")))