[英][Scala][Spark]: transform a column in dataframe, keeping other columns, using withColumn and map [error: missing parameter type]
我有 dataframe df
| name| languagesAtSchool|currentState|
+----------------+------------------+------------+
| James,,Smith|[Java, Scala, C++]| CA|
| Michael,Rose,|[Spark, Java, C++]| NJ|
|Robert,,Williams| [CSharp, VB, R]| NV|
+----------------+------------------+------------+
我想
+----------------+--------+-----+
|Name |language|State|
+----------------+--------+-----+
|James,,Smith |Java |CA |
|James,,Smith |Scala |CA |
|James,,Smith |C++ |CA |
|Michael,Rose, |Spark |NJ |
|Michael,Rose, |Java |NJ |
|Michael,Rose, |C++ |NJ |
|Robert,,Williams|CSharp |NV |
|Robert,,Williams|VB |NV |
|Robert,,Williams|R |NV |
+----------------+--------+-----+
我试过下面的方法,效果很好
val df2=df.flatMap(f=> f.getSeq[String](1).map((f.getString(0),_,f.getString(2))))
.toDF("Name","language","State")
但我希望在不指定其他列保留的情况下工作,因此我尝试了
val df2 = df.withColumn("laguage", df.flatMap(f=>f.getSeq[String](1)))
然后它给出
Unknown Error: <console>:40: error: missing parameter type
val df3 = df.withColumn("laguage", df.flatMap(f=>f.getSeq[String](1)))
^
因此,我希望 Spark 中的某些东西能够在不丢弃其他列的情况下转换列。 我猜原因是 scala 无法确定类型,但我无法修复它。 我是 scala 的新用户,感谢您的帮助!
explode
正是用于这种情况 - 它拆分一个数组列,因此列表中的每个元素都将位于单独的行中。
这是带有输出的完整示例:
package org.example
import org.apache.spark.sql._
import org.apache.spark.sql.functions.{col, explode}
import org.apache.spark.sql.types.{ArrayType, StringType, StructType}
object App {
def main(args: Array[String]): Unit = {
val spark: SparkSession = SparkSession.builder().appName("test").master("local[*]").getOrCreate()
import spark.implicits._
// create dataframe with test data
val data = Seq(
Row("James,,Smith", List("java", "scala"), "ca"),
Row("Robert,,Williams", List("c", "c++"), "nv")
)
val schema = new StructType()
.add("name", StringType)
.add("languages", ArrayType(StringType))
.add("current_state", StringType)
val df = spark.createDataFrame(spark.sparkContext.parallelize(data), schema)
df.show(false)
// +----------------+-------------+-------------+
// |name |languages |current_state|
// +----------------+-------------+-------------+
// |James,,Smith |[java, scala]|ca |
// |Robert,,Williams|[c, c++] |nv |
// +----------------+-------------+-------------+
// use explode to split the array values into different rows
df.withColumn("language", explode(col("languages"))).drop("languages").show()
// +----------------+-------------+--------+
// | name|current_state|language|
// +----------------+-------------+--------+
// | James,,Smith| ca| java|
// | James,,Smith| ca| scala|
// |Robert,,Williams| nv| c|
// |Robert,,Williams| nv| c++|
// +----------------+-------------+--------+
}
}
您正在寻找的方法是explode
:
def explode(e: Column): Column 为给定数组或 map 列中的每个元素创建一个新行。 除非另有说明,否则对数组中的元素使用默认列名 col,对 map 中的元素使用默认列名 key 和 value。 从 1.3.0 开始
df.withColumn("language", explode(col("language"))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.