Fendre 1 colonne en 3 colonnes en spark scala

j'ai une base de données en Spark en utilisant scala qui a une colonne que j'ai besoin de diviser.

scala> test.show
+-------------+
|columnToSplit|
+-------------+
|        a.b.c|
|        d.e.f|
+-------------+

j'ai besoin que cette colonne se divise pour ressembler à ceci:

+--------------+
|col1|col2|col3|
|   a|   b|   c|
|   d|   e|   f|
+--------------+

j'utilise Spark 2.0.0

Merci

17
demandé sur Matt Maurer 2016-08-31 20:47:31

4 réponses

Essaie:

df.withColumn("_tmp", split($"columnToSplit", "\.")).select(
  $"_tmp".getItem(0).as("col1"),
  $"_tmp".getItem(1).as("col2"),
  $"_tmp".getItem(2).as("col3")
).drop("_tmp")
34
répondu 2 revsuser6022341 2016-08-31 17:58:41

une solution qui évite la partie select. Cette fonction est utile lorsque vous voulez juste ajouter de nouvelles colonnes:

case class Message(others: String, text: String)

val r1 = Message("foo1", "a.b.c")
val r2 = Message("foo2", "d.e.f")

val records = Seq(r1, r2)
val df = spark.createDataFrame(records)

df.withColumn("col1", split(col("text"), "\.").getItem(0))
  .withColumn("col2", split(col("text"), "\.").getItem(1))
  .withColumn("col3", split(col("text"), "\.").getItem(2))
  .show(false)

+------+-----+----+----+----+
|others|text |col1|col2|col3|
+------+-----+----+----+----+
|foo1  |a.b.c|a   |b   |c   |
|foo2  |d.e.f|d   |e   |f   |
+------+-----+----+----+----+

mise à Jour: je vous recommande fortement d'utiliser mise en oeuvre de Psidom pour éviter de se séparer trois fois.

14
répondu Sascha Vetter 2018-09-24 20:16:07

pour faire cela programmatiquement, vous pouvez créer une séquence d'expressions avec (0 until 3).map(i => col("temp").getItem(i).as(s"col$i")) (suppose que vous avez besoin de 3 colonnes comme résultat) et ensuite l'appliquer à select: _* syntaxe:

df.withColumn("temp", split(col("columnToSplit"), "\.")).select(
    (0 until 3).map(i => col("temp").getItem(i).as(s"col$i")): _*
).show
+----+----+----+
|col0|col1|col2|
+----+----+----+
|   a|   b|   c|
|   d|   e|   f|
+----+----+----+

Pour garder toutes les colonnes:

df.withColumn("temp", split(col("columnToSplit"), "\.")).select(
    col("*") +: (0 until 3).map(i => col("temp").getItem(i).as(s"col$i")): _*
).show
+-------------+---------+----+----+----+
|columnToSplit|     temp|col0|col1|col2|
+-------------+---------+----+----+----+
|        a.b.c|[a, b, c]|   a|   b|   c|
|        d.e.f|[d, e, f]|   d|   e|   f|
+-------------+---------+----+----+----+
10
répondu Psidom 2017-08-31 03:34:52

ceci ajoute des colonnes à la base de données originale et n'utilise pas select, et seulement divise une fois en utilisant une temporaire de la colonne:

import spark.implicits._

df.withColumn("_tmp", split($"columnToSplit", "\."))
  .withColumn("col1", $"_tmp".getItem(0))
  .withColumn("col2", $"_tmp".getItem(1))
  .withColumn("col3", $"_tmp".getItem(2))
  .drop("_tmp")
2
répondu soaptree 2018-05-02 01:11:34