web-dev-qa-db-ja.com

SparkSQL DataFrameのMapType列からキーと値を取得する方法

2つのフィールドがある_object_id: String_と_alpha: Map<>_という寄木細工のファイルにデータがあります。

これは、sparkSQLのデータフレームに読み込まれ、スキーマは次のようになります。

_scala> alphaDF.printSchema()
root
 |-- object_id: string (nullable = true)
 |-- ALPHA: map (nullable = true)
 |    |-- key: string
 |    |-- value: struct (valueContainsNull = true)
_

私はSpark 2.0を使用しており、列を_object_id_に加えて_ALPHAマップのキーにする必要がある新しいデータフレームを_object_id, key1, key2, key2, ..._

私は最初に、少なくとも次のようにマップにアクセスできるかどうかを確認しようとしました。

_scala> alphaDF.map(a => a(0)).collect()
<console>:32: error: Unable to find encoder for type stored in a Dataset.
Primitive types (Int, String, etc) and Product types (case classes) are 
supported by importing spark.implicits._  Support for serializing other
types will be added in future releases.
   alphaDF.map(a => a(0)).collect()
_

しかし残念ながら、マップのキーにアクセスする方法を理解することができないようです。

誰かが_object_id_およびマップキーを列名として取得し、値を新しいデータフレームのそれぞれの値として取得する方法を教えてもらえますか?

11
lloydh

スパーク> = 2.

map_keys関数を使用してプロセスを簡略化できます。

import org.Apache.spark.sql.functions.map_keys

map_values関数もありますが、ここでは直接役立ちません。

スパーク<2.

一般的な方法は、数ステップで表現できます。最初に必要なインポート:

import org.Apache.spark.sql.functions.udf
import org.Apache.spark.sql.Row

およびサンプルデータ:

val ds = Seq(
  (1, Map("foo" -> (1, "a"), "bar" -> (2, "b"))),
  (2, Map("foo" -> (3, "c"))),
  (3, Map("bar" -> (4, "d")))
).toDF("id", "alpha")

キーを抽出するには、UDFを使用できます(Spark <2.3)

val map_keys = udf[Seq[String], Map[String, Row]](_.keys.toSeq)

または組み込み関数

import org.Apache.spark.sql.functions.map_keys

val keysDF = df.select(map_keys($"alpha"))

異なるものを見つける:

val distinctKeys = keysDF.as[Seq[String]].flatMap(identity).distinct
  .collect.sorted

keysexplodeで一般化することもできます:

import org.Apache.spark.sql.functions.explode

val distinctKeys = df
  // Flatten the column into key, value columns
 .select(explode($"alpha"))
 .select($"key")
 .as[String].distinct
 .collect.sorted

そしてselect

ds.select($"id" +: distinctKeys.map(x => $"alpha".getItem(x).alias(x)): _*)
19
user6910411

そして、あなたがPySparkにいるなら、私は簡単な実装を見つけます:

from pyspark.sql.functions import map_keys

alphaDF.select(map_keys("ALPHA").alias("keys")).show()

詳細は こちら で確認できます

0
Hailin FU