web-dev-qa-db-ja.com

Spark dataframeでネストされたStructを展開する

Databricks を使用しています。データフレームのスキーマは次のようになります。

> parquetDF.printSchema
root
|-- department: struct (nullable = true)
|    |-- id: string (nullable = true)
|    |-- name: string (nullable = true)
|-- employees: array (nullable = true)
|    |-- element: struct (containsNull = true)
|    |    |-- firstName: string (nullable = true)
|    |    |-- lastName: string (nullable = true)
|    |    |-- email: string (nullable = true)
|    |    |-- salary: integer (nullable = true)

この例では、従業員列を4つの追加列に分解する方法を示しています。

val explodeDF = parquetDF.explode($"employees") { 
case Row(employee: Seq[Row]) => employee.map{ employee =>
  val firstName = employee(0).asInstanceOf[String]
  val lastName = employee(1).asInstanceOf[String]
  val email = employee(2).asInstanceOf[String]
  val salary = employee(3).asInstanceOf[Int]
  Employee(firstName, lastName, email, salary)
 }
}.cache()
display(explodeDF)

部署の列で同様のことを行うにはどうすればよいですか(つまり、「id」と「name」という2つの列をデータフレームに追加します)。方法はまったく同じではなく、次を使用してまったく新しいデータフレームを作成する方法しかわかりません。

val explodeDF = parquetDF.select("department.id","department.name")
display(explodeDF)

私が試した場合:

val explodeDF = parquetDF.explode($"department") { 
  case Row(dept: Seq[String]) => dept.map{dept => 
  val id = dept(0) 
  val name = dept(1)
  } 
}.cache()
display(explodeDF)

警告とエラーが表示されます:

<console>:38: warning: non-variable type argument String in type pattern Seq[String] is unchecked since it is eliminated by erasure
            case Row(dept: Seq[String]) => dept.map{dept => 
                           ^
<console>:37: error: inferred type arguments [Unit] do not conform to    method explode's type parameter bounds [A <: Product]
  val explodeDF = parquetDF.explode($"department") { 
                                   ^
19
Feynman27

次のようなものを使用できます。

var explodeDF = explodeDF.withColumn("id", explodeDF("department.id"))
explodeDeptDF = explodeDeptDF.withColumn("name", explodeDeptDF("department.name"))

あなたが私を助け、これらの質問:

14
gsamaras

私の意見では、最もエレガントなソリューションは、以下に示すように、選択演算子を使用してStructをスター展開することです。

var explodedDf2 = explodedDf.select("department.*","*")

https://docs.databricks.com/spark/latest/spark-sql/complex-types.html

8
DHARIN PAREKH

これは動作するようです(ただし、最もエレガントなソリューションではないかもしれません).

var explodeDF2 = explodeDF.withColumn("id", explodeDF("department.id"))
explodeDF2 = explodeDF2.withColumn("name", explodeDF2("department.name"))
3
Feynman27