Scala 将 WrappedArray 或 Array[Any] 转换为 Array[String]

Posted

技术标签:

【中文标题】Scala 将 WrappedArray 或 Array[Any] 转换为 Array[String]【英文标题】:Scala convert WrappedArray or Array[Any] to Array[String] 【发布时间】:2018-01-19 10:35:27 【问题描述】:

我一直在尝试将 RDD 转换为数据帧。为此,需要定义类型而不是任何类型。我正在使用 spark MLLib PrefixSpan,这就是 freqSequence.sequence 的来源。我从一个包含 Session_ID、视图和购买作为字符串数组的数据框开始:

viewsPurchasesGrouped: org.apache.spark.sql.DataFrame =
  [session_id: decimal(29,0), view_product_ids: array[string], purchase_product_ids: array[string]]

然后我计算频繁模式并在数据框中需要它们,以便我可以将它们写入 Hive 表。

val viewsPurchasesRddString = viewsPurchasesGrouped.map( row => Array(Array(row(1)), Array(row(2)) ))

val prefixSpan = new PrefixSpan()
  .setMinSupport(0.001)
  .setMaxPatternLength(2)

val model = prefixSpan.run(viewsPurchasesRddString)

val freqSequencesRdd = sc.parallelize(model.freqSequences.collect())

case class FreqSequences(views: Array[String], purchases: Array[String], support: Long)

val viewsPurchasesDf = freqSequencesRdd.map( fs =>
     
  val views = fs.sequence(0)(0)
  val purchases = fs.sequence(1)(0)
  val freq = fs.freq
  FreqSequences(views, purchases, freq)
  
)
viewsPurchasesDf.toDF() // optional

当我尝试运行它时,浏览量和购买量是“Any”而不是“Array[String]”。我拼命尝试转换它们,但我得到的最好的是 Array[Any]。我想我需要将内容映射到一个字符串,我试过了,例如这个:How to get an element in WrappedArray: result of Dataset.select("x").collect()? 和这个:How to cast a WrappedArray[WrappedArray[Float]] to Array[Array[Float]] in spark (scala) 以及其他数千个 *** 问题......

我真的不知道如何解决这个问题。我想我已经将初始数据帧/RDD 转换为很多,但不明白在哪里。

【问题讨论】:

【参考方案1】:

我解决了这个问题。作为参考,这是可行的:

val viewsPurchasesRddString = viewsPurchasesGrouped.map( row =>
  Array(
  row.getSeq[Long](1).toArray, 
  row.getSeq[Long](2).toArray
  )
)

val prefixSpan = new PrefixSpan()
  .setMinSupport(0.001)
  .setMaxPatternLength(2)

val model = prefixSpan.run(viewsPurchasesRddString)

case class FreqSequences(views: Long, purchases: Long, frequence: Long)

val ps_frequences = model.freqSequences.filter(fs => fs.sequence.length > 1).map( fs =>
       
    val views = fs.sequence(0)(0)
    val purchases = fs.sequence(1)(0)
    val freq = fs.freq
    FreqSequences(views, purchases, freq)
    
)

ps_frequences.toDF()

【讨论】:

【参考方案2】:

我认为问题在于您有一个DataFrame,它不保留任何静态类型信息。当您从Row 中取出一个项目时,您必须明确告诉它您希望获得哪种类型。

未经测试,但根据您提供的信息推断:

import scala.collection.mutable.WrappedArray

val viewsPurchasesRddString = viewsPurchasesGrouped.map( row =>
  Array(
    Array(row.getAs[WrappedArray[String]](1).toArray), 
    Array(row.getAs[WrappedArray[String]](2).toArray)
  )
)

【讨论】:

感谢您的回答!尝试此操作时,我收到此错误消息:viewsPurchasesRddString: org.apache.spark.rdd.RDD[Array[Array[Array[String]]]] = MapPartitionsRDD[1801] at map at <console>:197 prefixSpan: org.apache.spark.mllib.fpm.PrefixSpan = org.apache.spark.mllib.fpm.PrefixSpan@13b756c2 org.apache.spark.SparkException: Job aborted due to stage failure: Task 28 in stage 1272.0 failed 4 times, most recent failure: Lost task 28.3 in stage 1272.0 (...): java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [Ljava.lang.String; 不幸的是,即使导入,我也会遇到同样的错误。

以上是关于Scala 将 WrappedArray 或 Array[Any] 转换为 Array[String]的主要内容,如果未能解决你的问题,请参考以下文章

WrappedArray$ofRef 不能转换为 scala.collection.immutable.Seq

如何在 Spark Scala 中将 WrappedArray 转换为 List?

spark提示Caused by: java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot b

Scala可变参数方法或者函数传参问题

如何检查列数据 Spark scala 上的 isEmpty

从火花数据帧中读取结构[重复]