将多个(任意数量)火花 DataFrame 列连接成一个“|”分隔字符串

Posted

技术标签:

【中文标题】将多个(任意数量)火花 DataFrame 列连接成一个“|”分隔字符串【英文标题】:Concatenating multiple (any number) spark DataFrame columns into one "|" deliminated string 【发布时间】:2019-04-30 17:44:24 【问题描述】:

我有一个 DataFrame 和一个作为字符串的列列表,我需要在原始数据框中添加一个列,该列是 | 分隔的值列表,其中 null 变成字符串 @987654323 @

这是我目前拥有的代码:

def mergeColumns(cols: Array[String], df: DataFrame, newName: String): DataFrame = 
  val dfColumns = cols.map( columnName => df(columnName) )
  df.withColumn(newName, concatenate(array(dfColumns: _*), lit("|")))

val concatenate: UserDefinedFunction = udf( (columns: Seq[Any], separator: String) => 
  columns.map(
    case null => "null"
    case default => default.toString
  ).mkString(separator)
)

并且该代码有效,但前提是所有提供的列都属于同一类型,并且我当前的计划是尝试将它们全部转换为 String 类型。所以我有两个问题: 1)一般来说有没有更好的方法来做到这一点? 2)如果没有,我如何将所有dfColumns 列转换为字符串?

【问题讨论】:

【参考方案1】:

您可以在 Row 类上使用 mkString 来做到这一点:

val df =Seq(
  ("a", "b",Option.empty[String])
).toDF("Col1","Col2","Col3")

val makeString = udf((r : Row) => r.mkString("|"))

df.withColumn("newCol",makeString(struct("*")))
  .show()

给予

+----+----+----+--------+
|Col1|Col2|Col3|  newCol|
+----+----+----+--------+
|   a|   b|null|a|b|null|
+----+----+----+--------+

【讨论】:

如果我只想要这些列的一个子集怎么办,比如Col2Col3。我仍然想要原来的列,所以架构仍然是Col1, Col2, Col3, newCol 我找到了问题的答案,只需使用struct(columns: _*) 代替struct("*"),其中columns 是原帖中的dfColumns【参考方案2】:

尝试使用 fill null valuesconcat_ws 函数。

前:

val df =Seq(
           ("a", "b",Option.empty[String]))
           .toDF("Col1","Col2","Col3")
df.na.fill("null")
     .withColumn("cn_ws",concat_ws("|", array("*")))
     .show(false)

结果:

+----+----+----+--------+
|Col1|Col2|Col3|cn_ws   |
+----+----+----+--------+
|a   |b   |null|a|b|null|
+----+----+----+--------+

更新:

将所有列投射到 "string"

df.na.fill("null")
     .withColumn("cn_ws", 
       concat_ws("|", array(df.columns.map(c => col(c).cast(StringType)): _*)))
     .show(false)

【讨论】:

根据文档:Concatenates multiple input string columns together into a single string column, using the given separator. 有没有办法确保所有列都是字符串列? @JaredDuPont,请检查我的更新答案..! :-)

以上是关于将多个(任意数量)火花 DataFrame 列连接成一个“|”分隔字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spark DataFrame 中将多个浮点列连接到一个 ArrayType(FloatType()) 中?

如何将一个 DataFrame 中的多个列与另一个 DataFrame 连接

将多个 DataFrame 与非标准列连接起来

如何根据火花DataFrame中另一列的值更改列的值

如何通过比较火花中相同列的两个数据帧来计算列值的数量

通过加入多个 DataFrame 来连接列