簡體   English   中英

Spark DataFrame映射錯誤

[英]Spark DataFrame map error

抱歉,我需要再問一個問題。 我希望這不是重復的。 我編輯了最后一個 ,但是我認為沒有人看到編輯過的版本。 這是問題的簡短示例:

val spark = SparkSession
.builder()
.appName("test")
.getOrCreate()

val field = StructField("1", BooleanType, false)
val schema = StructType(field::Nil)
val rowRDD = spark.sparkContext.parallelize(Array(Row(true),Row(false)))
val df = spark.createDataFrame(rowRDD, schema)

val new_df = //Add hundred of new columns

//here is the error
val df_2 = new_df.flatMap(row => if(test(row)) row::Nil else Nil)

錯誤:

error: Unable to find encoder for type stored in a Dataset.  
Primitive types (Int, String, etc) and Product types (case classes) are supported by importing spark.implicits._  
Support for serializing other types will be added in future releases.

我想要做的是修改每一行。 在這種情況下,我知道只有1列,並且在嘗試將dataframe行映射到更新的row時,可以像編碼器錯誤一樣處理它。 但是,如果我有數百列,如何解決該問題? 我想刪除一些不滿足條件的行。 目前,我使用:

val df_2 = new_df.rdd.flatMap(row => if(test(row)) row::Nil else Nil)

但是我不認為這是最好的解決方案。 我也在StackoverflowError中運行:

Exception in thread "main" java.lang.StackOverflowError
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1189)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at scala.collection.immutable.List$SerializationProxy.writeObject(List.scala:468)

TY尋求幫助:)

添加新列的withColumn()選項將適用於整個數據集。 而且,如果您有更多的列,則情況將變得更糟。 您可以使用Spark SQL並使用SQL樣式的查詢來添加新列。 這將需要更多的SQL技能,而不僅僅是spark。 擁有100根色譜柱,可能很難進行維護。

您可以采用另一種方法。

您可以將rdd轉換為數據幀。 然后在數據框上使用map並根據需要處理每一行。 內部地圖方法

一種。 您可以根據計算結果收集新值

b。 將這些新列值添加到main rdd中,如下所示

val newColumns: Seq[Any] = Seq(newcol1,newcol2)
Row.fromSeq(row.toSeq.init ++ newColumns)

這里的row是map方法中該行的引用

C。 如下創建新架構

val newColumnsStructType = StructType{Seq(new StructField("newcolName1",IntegerType),new StructField("newColName2", IntegerType))

d。 添加到舊模式

val newSchema = StructType(mainDataFrame.schema.init ++ newColumnsStructType)

使用新列創建新數據框

val newDataFrame = sqlContext.createDataFrame(newRDD, newSchema)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM