Spark DataFrame - как преобразовать один столбец в несколько строк - PullRequest
0 голосов
/ 27 мая 2020

Необходимо преобразовать одну строку в несколько столбцов. Сделал следующие вещи.

val list = List("a", "b", "c", "d")

  import spark.implicits._

  val df = list.toDF("id")

  df.show()

  import spark.implicits._

   val transpose = list.zipWithIndex.map {
    case (_, index) => col("data").getItem(index).as(s"col_${index}")
  }

  df.select(collect_list($"id").as("data")).select(transpose: _*).show()

вывод:

+-----+-----+-----+-----+
|col_0|col_1|col_2|col_3|
+-----+-----+-----+-----+
|    a|    b|    c|    d|
+-----+-----+-----+-----+

Сделал что-то и преобразовал это. Но проблема с функцией транспонирования, она передает исходные данные (список). Если мы сделаем какой-либо фильтр в df, он всегда будет показывать 4 столбца, поскольку исходный список имеет 4. Как я могу сократить этот список.

Добавление дополнительной информации

df.filter($"id" =!="a" ).select(collect_list($"id").as("data")).select(transpose: _*).show()\

если применить условие фильтра и показать команду

+-----+-----+-----+-----+
|col_0|col_1|col_2|col_3|
+-----+-----+-----+-----+
|    b|    c|    d| null|
+-----+-----+-----+-----+

, что неверно и должно отображать 3 столбца, а не 4 столбца.

Ответы [ 2 ]

2 голосов
/ 27 мая 2020

вы можете сделать это с помощью pivot:

val df = List("a", "b", "c", "d").toDF("id")

val dfFiltered = df.filter($"id"=!="a")

dfFiltered
  .groupBy().pivot($"id").agg(first($"id"))
  .toDF((0 until dfFiltered.count().toInt).map(i => s"col_$i"):_*)
  .show()

+-----+-----+-----+
|col_0|col_1|col_2|
+-----+-----+-----+
|    b|    c|    d|
+-----+-----+-----
0 голосов
/ 27 мая 2020

Проделал какой-то трюк с обрезкой столбцов на основе количества строк df. Сообщите мне, если это поможет

import org.apache.spark.sql.functions._

object TransposeV2 {

  def main(args: Array[String]): Unit = {
    val spark = Constant.getSparkSess

    val list = List("a", "b", "c", "d")

    import spark.implicits._

    val df = list.toDF("id")

    df.show()

    import spark.implicits._

    val transpose = list.zipWithIndex.map {
      case (_, index) => {
        col("data").getItem(index).as(s"col_${index}")
      }
    }

    df.select(collect_list($"id").as("data")).select(transpose: _*).show()

    val dfInterim = df.filter($"id" =!="a" )
    val finalElements : Int = dfInterim.count().toInt
    dfInterim.select(collect_list($"id").as("data")).select(transpose.take(finalElements): _*).show()
  }

}

...