以下操作正常:
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.{StructField,StructType,IntegerType, ArrayType, LongType}
val df = sc.parallelize(Seq((1.0, 2.0), (0.0, -1.0), (3.0, 4.0), (6.0, -2.3))).toDF("x", "y")
val newSchema = StructType(df.schema.fields ++ Array(StructField("rowid", LongType, false)))
val rddWithId = df.rdd.zipWithIndex
val dfZippedWithId = spark.createDataFrame(rddWithId.map{ case (row, index) => Row.fromSeq(row.toSeq ++ Array(index))}, newSchema)
此结构:
rddWithZipId: org.apache.spark.rdd.RDD[((String, Int, Array[String]), Long)] = ZippedWithIndexRDD[149] at zipWithIndex at command-2467674133341972:32
当我做与先前示例完全相同的操作时,会产生错误。唯一的区别是Array [String]。
产生的错误是:
notebook:45: error: value toSeq is not a member of (String, Int, Array[String])
val dfPosts = spark.createDataFrame(rddWithZipId.map{ case (row, index) => Row.fromSeq(row.toSeq ++ Array(index))}, newSchema)
环顾四周,我看不到为什么这行不通。我注意到,即使我在RDD中看到4个类型/元素,也可以观察到Row被视为1个结构。
有什么想法吗?还有其他可能的方法,但是我不明白为什么第一个示例有效而第二个示例无效? Array [String]似乎是罪魁祸首。实际上必须如此,但是如何解决呢?
只需这样做:
val dfPosts = rddWithZipId.toDF()
按如下所示返回嵌套模式,所以可能是这样,但是尽管如此,问题依旧。嵌套结构意味着我可以实现我想做的事情,这不是问题。
root
|-- _1: struct (nullable = true)
| |-- _1: string (nullable = true)
| |-- _2: integer (nullable = false)
| |-- _3: array (nullable = true)
| | |-- element: string (containsNull = true)
|-- _2: long (nullable = false)
我认为需要以某种方式定义嵌套结构。
谢谢。
答案 0 :(得分:0)
还有其他可能的方法,但是我不明白为什么第一个示例有效而第二个示例无效? Array [String]似乎是罪魁祸首。
与第一个元素的内容无关。这都是关于类型的。如果您查看类型rddWithId
是
RDD[(Row, Long)]
第二个结构是
RDD[((String, Int, Array[String]), Long)]
因此,在第一种情况下,_1
是提供org.apache.spark.sql.Row
方法的toSeq
,而在第二种情况下,_1
是Tuple3[_, _, _]
,它没有提供这种方法方法。
如果要使其正常运行
Row.fromSeq(row.toSeq ++ Array(index))
替换
Row.fromSeq(("a", 1, Array("foo")).productIterator.toSeq ++ Array(index))
或更好(为什么要为每个呼叫初始化额外的Array
?)
Row.fromSeq(("a", 1, Array("foo")).productIterator.toSeq :+ index)