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その他のドライバースタックトレース:
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プログラミングガイド を参照してください。