web-dev-qa-db-ja.com

タイプArray [string]の2つのspark sql列を新しいArray [string]列にマージします

Spark SQL DataFrameに2つの列があります。各エントリは文字列の配列としていずれかの列にあります。

val  ngramDataFrame = Seq(
  (Seq("curious", "bought", "20"), Seq("iwa", "was", "asj"))
).toDF("filtered_words", "ngrams_array")

各行の配列をマージして、新しい列に単一の配列を作成します。私のコードは次のとおりです:

def concat_array(firstarray: Array[String], 
                 secondarray: Array[String]) : Array[String] = 
                                     { (firstarray ++ secondarray).toArray }
val concatUDF = udf(concat_array _)
val concatFrame = ngramDataFrame.withColumn("full_array", concatUDF($"filtered_words", $"ngrams_array"))

concat_array 2つの配列に対する関数。ただし、上記のコードを実行すると、次の例外が発生します。

org.Apache.spark.SparkException:ステージの失敗によりジョブが中止されました:ステージ16.0のタスク0が1回失敗しました。最新の失敗:ステージ16.0のタスク0.0が失われました(TID 12、localhost):org.Apache.spark.SparkException:失敗しましたorg.Apache.spark.sql.executionでorg.Apache.spark.sql.catalyst.expressions.GeneratedClass $ GeneratedIterator.processNext(Unknown Source)でユーザー定義関数(anonfun $ 1:(array、array)=> array)を実行する.BufferedRowIterator.hasNext(BufferedRowIterator.Java:43)at org.Apache.spark.sql.execution.WholeStageCodegenExec $$ anonfun $ 8 $$ anon $ 1.hasNext(WholeStageCodegenExec.scala:370)at scala.collection.Iterator $$ anon .hasNext(Iterator.scala:389)at scala.collection.Iterator $$ anon $ 11.hasNext(Iterator.scala:408)at org.Apache.spark.shuffle.sort.BypassMergeSortShuffleWriter.write(BypassMergeSortShuffleWriter.Java:125)at org.Apのorg.Apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:47)のorg.Apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:79) ache.spark.scheduler.Task.run(Task.scala:86)at org.Apache.spark.executor.Executor $ TaskRunner.run(Executor.scala:274)at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor。 Java:1149)at Java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.Java:624)at Java.lang.Thread.run(Thread.Java:748)原因:Java.lang.ClassCastException:scala.collection .mutable.WrappedArray $ ofRefは[Ljava.lang.String;にキャストできません。 $ line80。$ read $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ anonfun $ 1.apply(:76)... 13その他のドライバースタックトレース:

5
Arjun Mishra

Arjun作成したudfにエラーがあります。配列型の列を渡そうとすると、.data型がArray [String]ではなく、WrappedArray [String]になります。以下では、変更されたudfを出力とともに貼り付けています。

val SparkCtxt = new SparkContext(sparkConf)

val sqlContext = new SQLContext(SparkCtxt)

import sqlContext.implicits

import org.Apache.spark.sql.functions._
val temp=SparkCtxt.parallelize(Seq(Row(Array("String1","String2"),Array("String3","String4"))))
val df= sqlContext.createDataFrame(temp,
  StructType(List(
    StructField("Col1",ArrayType(StringType),true),
    StructField("Col2",ArrayType(StringType),true)
  )
  )    )

def concat_array(firstarray: mutable.WrappedArray[String],
                 secondarray: mutable.WrappedArray[String]) : mutable.WrappedArray[String] =
{
 (firstarray ++ secondarray)
}
val concatUDF = udf(concat_array _)
val df2=df.withColumn("udftest",concatUDF(df.col("Col1"), df.col("Col2")))
df2.select("udftest").foreach(each=>{println("***********")
println(each(0))})
df2.show(true)

出力:

+------------------+------------------+--------------------+
|              Col1|              Col2|             udftest|
+------------------+------------------+--------------------+
|[String1, String2]|[String3, String4]|[String1, String2...|
+------------------+------------------+--------------------+

WrappedArray(文字列1、文字列2、文字列3、文字列4)

Spark 2.4以降では、concatを使用できます(重複を保持したい場合):

ngramDataFrame.withColumn(
  "full_array", concat($"filtered_words", $"ngrams_array")
).show
+--------------------+---------------+--------------------+
|      filtered_words|   ngrams_array|          full_array|
+--------------------+---------------+--------------------+
|[curious, bought,...|[iwa, was, asj]|[curious, bought,...|
+--------------------+---------------+--------------------+

またはarray_union(重複を削除する場合):

ngramDataFrame.withColumn(
  "full_array",
   array_union($"filtered_words", $"ngrams_array")
)

これらは、他の高次関数から構成することもできます。たとえば、

ngramDataFrame.withColumn(
   "full_array",
   flatten(array($"filtered_words", $"ngrams_array"))
)

重複あり、および

ngramDataFrame.withColumn(
   "full_array",
   array_distinct(flatten(array($"filtered_words", $"ngrams_array")))
)

なし。

余談ですが、WrappedArray列を操作する場合はArrayTypeを使用しないでください。代わりに、保証されたインターフェースであるSeqを期待する必要があります。したがって、udfは次のシグネチャを持つ関数を使用する必要があります:

(Seq[String], Seq[String]) => Seq[String]

詳細は SQLプログラミングガイド を参照してください。

10
user6910411