Объединение нескольких (любого числа) столбцов искривления DataFrame в один «|» исключенная строка - PullRequest
1 голос
/ 30 апреля 2019

У меня есть DataFrame и список столбцов в виде строк, и мне нужно добавить столбец к исходному фрейму данных, который представляет собой разделенный | список значений, где null превращается в строку "null"

Это код, который у меня сейчас есть:

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 в строки?

Ответы [ 2 ]

3 голосов
/ 30 апреля 2019

Вы можете сделать это, используя mkString в классе Row:

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|
+----+----+----+--------+
0 голосов
/ 01 мая 2019

Попробуйте с функциями fill null values и concat_ws.

EX:

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|
+----+----+----+--------+

UPDATE:

Приведите все столбцы к "string"

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