【问题标题】:Concatenating multiple (any number) spark DataFrame columns into one "|" deliminated string将多个(任意数量)火花 DataFrame 列连接成一个“|”分隔字符串
【发布时间】: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 列转换为字符串?

【问题讨论】:

    标签: scala apache-spark dataframe user-defined-functions


    【解决方案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,请检查我的更新答案..! :-)
    猜你喜欢
    • 2012-02-02
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2016-08-17
    • 2014-03-15
    • 2013-05-15
    相关资源
    最近更新 更多