![](/img/trans.png)
[英]java.lang.ClassCastException: org.apache.spark.sql.Column cannot be cast to scala.collection.Seq
[英]How to apply UDF to collected Rows? (fails with “java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.spark.sql.Column”)
我有兩個數據框,一個包含這樣的數據
第一個數據框是這樣的
+-----+-----------+-----+----------------------+
|value|mergeValues|table|columnName |
+-----+-----------+-----+----------------------+
|1 |1,2,3 | |columnName1 |
|2 |4,5,6,7 | |columnName1 |
|3 |8,9 | |columnName1 |
|1 |1,2,3 | |columnName4 |
|2 |4,5,6,7 | |columnName4 |
|3 |8,9 | |columnName4 |
|1 |1,2,3 | |columnName5 |
|2 |4,5,6,7 | |columnName5 |
|3 |8,9 | |columnName5 |
|1 |1,2,3 | |columnName6 |
+-----+-----------+-----+----------------------+
另一個數據框結構如下所示
columnName1 | columnName2 | columnName3 |columnName4 |columnName5 | columnName6
1
3
2
4
5
現在,我必須像這樣創建映射的數據框。
Mapping logic is : get value from 2ndDF and check firstdf mergeValue if that contains then map to firstdf value. here value of 2nd df columnName1 is 1 it is present in firstDf mergeValues list map it to firstDf[value] which is 1. same for 2,3,4,5,6,7 ...
columnName1 | columnName2 | columnName3 |columnName4 |columnName5 | columnName6
1
1
1
2
2
為此,我使用UDF方式,但是失敗了,創建此數據框的正確方法是什么。
我的代碼是:
val firstDF=sparkSession.read.load(first)
val testDF = sparkSession.read.load(test)
val populateColumn: ((String, String, String) => String) = (mergeValues: String, value: String,
actualValue: String) => {
if (mergeValues.contains(actualValue.trim)) {
value
} else {
actualValue
}
}
val populateColumnUdf = udf(populateColumn)
val firstDFList=firstDF.collect
firstDFList.foreach(Case => {
println(Case)
testDF.withColumn(Case.getAs("columnName"), populateColumnUdf(Case.getAs("mergeValues"),
Case.getAs("value"), col(Case.getAs("columnName"))))
})
testDF.show
這是我得到的錯誤
java.lang.String無法轉換為org.apache.spark.sql.Column java.lang.ClassCastException:java.lang.String無法轉換為org.apache.spark.sql.Column
檢查執行以下操作的部分中的類型:
populateColumnUdf(Case.getAs("mergeValues"), Case.getAs("value"), col(Case.getAs("columnName")))
Case
的類型為Row
, getAs
為您提供給定fieldName的值。 (請參閱org.apache.spark.sql.Row )。 那絕對不是您的populateColumnUdf
期望的Column
。 在這種情況下,您寧願使用populateColumn
Scala函數。 您已經離開了DataFrame / UDF上下文,並且僅在Scala中。
正如Jacek Laskowski所說,在您的代碼中, Case是org.apache.spark.sql.Row類型
在Row上調用getAs返回該行在特定字段處的值(例如,第一個數據幀中第一行的值在“ mergeValues”列為“ 1,2,3”)
withColumn方法需要兩個參數。 第一個參數是要替換的列的名稱,第二個參數是作為替換列的org.apache.spark.sql.Column 。
在第二個參數中,是您提供udf的位置。 udf將列作為參數。 這些輸入列的數據類型應對應於udf環繞的函數(在本例中為populateColumn )所期望的輸入類型。
不確定您的col()函數在代碼中提供給udf的參數內做什么。
如果我正確理解您的代碼,那么您將尋找類似以下的內容(此代碼不完整,無法運行):
val firstDF = sparkSession.read.load(first)
val testDF = sparkSession.read.load(test)
val populateColumn: ((String, String, String) => String) =
(mergeValues: String, value: String, actualValue: String) => {
if (mergeValues.contains(actualValue.trim)) {
value
} else {
actualValue
}
}
val populateColumnUdf = udf(populateColumn)
val replacementCol = new Column("columnName1")
//mergeValuesCol and valueCol needs to be the columns from firstDF
testDF.withColumn("columnName1", populateColumnUdf(mergeValuesCol, valueCol, replacementCol))
需要提供從firstDF的外部列(mergeValues和值)的值(參見withColumn下傳遞數據幀列和外部列表到UDF用於參考)。
或者也許考慮在給定條件的情況下合並/合並兩個數據框。
希望這會有所幫助! 謝謝編輯問題的人,這樣我才能理解問題在問:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.