我试图将Spark数据帧写入CSV,但由于数据帧的某些列有一个数组,如下所示:
|ID|ArrayOfString|Age|Gender|
+--+-------------+---+------+
|1 | [A,B,D] |22 | F |
|2 | [A,Y] |42 | M |
|3 | [X] |60 | F |
+--+-------------+---+------+
我收到错误:
CSV data source does not support array<string> data type
所以,我想迭代数据框的列,对于类型为数组的列,我想对它们进行字符串化mkString(", ")
我找到了以下链接,它在Python中做了类似的事情: https://hadoopist.wordpress.com/2016/08/05/spark-data-frame-check-for-any-column-values-with-n-and-y-and-convert-the-corresponding-column-to-boolean-using-pyspark/
我需要在Scala中完成,我的尝试是:\
df.dtypes.map(dtype =>
{
val colName = dtype[0]
val colType = dtype[1]
if (colType.contains("ArrayType")) {
df = df.withColumn(colName, df.col(colName).mkString(", ")).drop(df[colName])
}
})
但我是Scala的初学者,无法弄清楚如何解决这个问题。我在这里做错了什么?
答案 0 :(得分:2)
您可以汇编所有ArrayType
列的列表,并使用foldLeft
遍历列表以对数组列进行字符串化:
val df = Seq(
(1, Seq("A", "B", "C"), 22, "F"),
(2, Seq("A", "Y"), 42, "M"),
(3, Seq("X"), 60, "F")
).toDF("ID", "ArrayOfString", "Age", "Gender")
import org.apache.spark.sql.types._
val arrTypeCols = df.schema.fields.collect{
case StructField(name, ArrayType(_, _), _, _) => name
}
// arrTypeCols: Array[String] = Array(ArrayOfString)
val df2 = arrTypeCols.foldLeft( df )( (acc, c) =>
acc.withColumn( c, concat_ws(", ", df(c)) )
)
df2.show
// +---+-------------+---+------+
// | ID|ArrayOfString|Age|Gender|
// +---+-------------+---+------+
// | 1| A, B, C| 22| F|
// | 2| A, Y| 42| M|
// | 3| X| 60| F|
// +---+-------------+---+------+
答案 1 :(得分:1)
您必须创建circular = TRUE
函数才能将数组列更改为字符串列
udf
并且因为您不知道 arrayType列名,所以您需要一个递归函数来遍历import org.apache.spark.sql.functions._
val arrayToStringUdf = udf((array: collection.mutable.WrappedArray[String]) => array.mkString(", "))
列以检查{ {1}}并调用dataframe
函数
ArrayType
您可以在递归函数中创建udf
的列表
def recursiveFunction(dataFrame: DataFrame, dataTypes: List[Tuple2[String, String]]) : DataFrame = dataTypes match {
case x :: y => if (x._2.contains("ArrayType")) {
recursiveFunction(dataFrame.withColumn(x._1, arrayToStringUdf(col(x._1))), y)
}
else{
recursiveFunction(dataFrame, y)
}
case _ => dataFrame
}
所以完整的解决方案如下
Tuple2(colName, colType)
我希望答案很有帮助