Реализация Spark UnaryTransformer завершается ошибкой с scala.MatchError

Я внедряю UnaryTransformer в Spark 1.6.2. с этим интерфейсом:

class myUT(override val uid: String) extends UnaryTransformer[Seq[String], Seq[String], myUT] {
...
override protected def createTransformFunc: Seq[String] => Seq[String] = {
   _ => _.map(x => x + "s")
}

Это компилируется хорошо, но во время выполнения возвращает мне ошибку:

17/07/21 22:29:33 WARN TaskSetManager: Lost task 0.3 in stage 0.0 (TID 3, myhost.com.au): scala.MatchError: ArrayBuffer(<contents of my array>) (of class scala.collection.mutable.ArrayBuffer)
at org.apache.spark.sql.catalyst.CatalystTypeConverters$StringConverter$.toCatalystImpl(CatalystTypeConverters.scala:295)
    at org.apache.spark.sql.catalyst.CatalystTypeConverters$StringConverter$.toCatalystImpl(CatalystTypeConverters.scala:294)
    at org.apache.spark.sql.catalyst.CatalystTypeConverters$CatalystTypeConverter.toCatalyst(CatalystTypeConverters.scala:102)
    at org.apache.spark.sql.catalyst.CatalystTypeConverters$$anonfun$createToCatalystConverter$2.apply(CatalystTypeConverters.scala:401)
    at org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificUnsafeProjection.apply(Unknown Source)
    at org.apache.spark.sql.execution.Project$$anonfun$1$$anonfun$apply$1.apply(basicOperators.scala:51)
    at org.apache.spark.sql.execution.Project$$anonfun$1$$anonfun$apply$1.apply(basicOperators.scala:49)

Следующее, что я попробовал, было заменить

_ => _.map(x => x + "s")

с

_ => _

Таким образом, теоретически это не должно означать никаких изменений данных вообще! Но ошибка, которую я получил, была:

17/07/21 22:11:59 WARN TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0, myhost.com.au): scala.MatchError: WrappedArray(<contains of my array>) (of class scala.collection.mutable.WrappedArray$ofRef)
at org.apache.spark.sql.catalyst.CatalystTypeConverters$StringConverter$.toCatalystImpl(CatalystTypeConverters.scala:295)
    at org.apache.spark.sql.catalyst.CatalystTypeConverters$StringConverter$.toCatalystImpl(CatalystTypeConverters.scala:294)
    at org.apache.spark.sql.catalyst.CatalystTypeConverters$CatalystTypeConverter.toCatalyst(CatalystTypeConverters.scala:102)
    at org.apache.spark.sql.catalyst.CatalystTypeConverters$$anonfun$createToCatalystConverter$2.apply(CatalystTypeConverters.scala:401)
    at org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificUnsafeProjection.apply(Unknown Source)
    at org.apache.spark.sql.execution.Project$$anonfun$1$$anonfun$apply$1.apply(basicOperators.scala:51)
    at org.apache.spark.sql.execution.Project$$anonfun$1$$anonfun$apply$1.apply(basicOperators.scala:49)

Похоже, что тип исходящих данных все равно меняется. Как мне избежать этого?

Обновление: Следующее, что я пытался добавить.toArray на карту. Ошибка теперь такая:

[error] /sparkprj/src/main/scala/sp_txt.scala:43: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [B >: String]Array[B]
[error]  required: Seq[String]
[error]                                           ).toArray

Это может добавить некоторые детали, но не добавляет много к моему пониманию. Изучив несколько примеров mllib UnaryTransformer, я склонен полагать, что это ошибка в Catalyst.

1 ответ

Решение

Эта строка в определении класса myUT была неверной:

override protected def outputDataType: DataType = new ArrayType(StringType, true)

Когда я скопировал это определение класса из преобразователя String->String, я определил DataType как просто StringType. Виноват.

Другие вопросы по тегам