Ausgabe
Ich versuche, Funktionen in Scala zu definieren, die eine Liste von Zeichenfolgen als Eingabe verwenden und sie in die Spalten konvertieren, die an die im folgenden Code verwendeten Datenrahmen-Array-Argumente übergeben werden.
val df = sc.parallelize(Array((1,1),(2,2),(3,3))).toDF("foo","bar")
val df2 = df
.withColumn("columnArray",array(df("foo").cast("String"),df("bar").cast("String")))
.withColumn("litArray",array(lit("foo"),lit("bar")))
Genauer gesagt möchte ich Funktionen colFunction
und litFunction
(oder wenn möglich nur eine Funktion) erstellen, die eine Liste von Zeichenfolgen als Eingabeparameter verwendet und wie folgt verwendet werden kann:
val df = sc.parallelize(Array((1,1),(2,2),(3,3))).toDF("foo","bar")
val colString = List("foo","bar")
val df2 = df
.withColumn("columnArray",array(colFunction(colString))
.withColumn("litArray",array(litFunction(colString)))
Ich habe versucht, das colString
mit allen Transformationen einem Array von Spalten zuzuordnen, aber das funktioniert nicht.
Lösung
Spark 2.2+ :
Unterstützung für Seq
, Map
und Tuple
( struct
) Literale wurde in SPARK-19254 hinzugefügt . Laut Tests :
import org.apache.spark.sql.functions.typedLit
typedLit(Seq("foo", "bar"))
Funke < 2,2
Nur map
mit lit
und wickeln Sie mit ein array
:
def asLitArray[T](xs: Seq[T]) = array(xs map lit: _*)
df.withColumn("an_array", asLitArray(colString)).show
// +---+---+----------+
// |foo|bar| an_array|
// +---+---+----------+
// | 1| 1|[foo, bar]|
// | 2| 2|[foo, bar]|
// | 3| 3|[foo, bar]|
// +---+---+----------+
In Bezug auf die Umwandlung von Seq[String]
in Column
vom Typ Array
wird diese Funktionalität bereits bereitgestellt von:
def array(colName: String, colNames: String*): Column
oder
def array(cols: Column*): Column
Beispiel:
val cols = Seq("bar", "foo")
cols match { case x::xs => df.select(array(x, xs:_*))
// or
df.select(array(cols map col: _*))
Natürlich müssen alle Spalten vom gleichen Typ sein.
Beantwortet von – zero323
Antwort geprüft von – Katrina (FixError Volunteer)