首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从嵌套的结构化火花Dataframe中获取模式作为Spark

如何从嵌套的结构化火花Dataframe中获取模式作为Spark
EN

Stack Overflow用户
提问于 2019-07-16 19:00:03
回答 2查看 1K关注 0票数 0

我有一个使用下面代码创建的示例Dataframe

代码语言:javascript
复制
val data = Seq(
  Row(20.0, "dog"),
  Row(3.5, "cat"),
  Row(0.000006, "ant")
)

val schema = StructType(
  List(
    StructField("weight", DoubleType, true),
    StructField("animal_type", StringType, true)
  )
)

val df = spark.createDataFrame(
  spark.sparkContext.parallelize(data),
  schema
)

val actualDF = df.withColumn(
  "animal_interpretation",
  struct(
    (col("weight") > 5).as("is_large_animal"),
    col("animal_type").isin("rat", "cat", "dog").as("is_mammal")
  )
)

actualDF.show(false)

+------+-----------+---------------------+
|weight|animal_type|animal_interpretation|
+------+-----------+---------------------+
|20.0  |dog        |[true,true]          |
|3.5   |cat        |[false,true]         |
|6.0E-6|ant        |[false,false]        |
+------+-----------+---------------------+

此Spark的模式可以使用-

代码语言:javascript
复制
scala> actualDF.printSchema
root
 |-- weight: double (nullable = true)
 |-- animal_type: string (nullable = true)
 |-- animal_interpretation: struct (nullable = false)
 |    |-- is_large_animal: boolean (nullable = true)
 |    |-- is_mammal: boolean (nullable = true)

但是,我想以一个有3列的数据格式( field, type, nullable )的形式获得这个模式。模式的输出数据应该是这样的-

代码语言:javascript
复制
+-------------------------------------+--------------+--------+
|field                                |type          |nullable|
+-------------------------------------+--------------+--------+
|weight                               |double        |true    |        
|animal_type                          |string        |true    |       
|animal_interpretation                |struct        |false   |
|animal_interpretation.is_large_animal|boolean       |true    |
|animal_interpretation.is_mammal      |boolean       |true    |     
+----------------------------------------------------+--------+

我怎样才能在星火中实现这一点。我正在使用Scala进行编码。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-16 22:57:35

下面是一个完整的示例,包括您的代码。我使用了一些常见的flattenSchema方法进行匹配,就像Shankar做的那样遍历结构,但是没有让这个方法返回扁平的模式,而是使用了一个ArrayBuffer来聚合StructType的数据类型并返回ArrayBuffer。然后,我将ArrayBuffer转换为序列,最后使用Spark将序列转换为DataFrame。

代码语言:javascript
复制
import org.apache.spark.sql.types.{StructType, StructField, DoubleType, StringType}
import org.apache.spark.sql.functions.{struct, col}
import scala.collection.mutable.ArrayBuffer

val data = Seq(
  Row(20.0, "dog"),
  Row(3.5, "cat"),
  Row(0.000006, "ant")
)

val schema = StructType(
  List(
    StructField("weight", DoubleType, true),
    StructField("animal_type", StringType, true)
  )
)

val df = spark.createDataFrame(
  spark.sparkContext.parallelize(data),
  schema
)

val actualDF = df.withColumn(
  "animal_interpretation",
  struct(
    (col("weight") > 5).as("is_large_animal"),
    col("animal_type").isin("rat", "cat", "dog").as("is_mammal")
  )
)

var fieldStructs = new ArrayBuffer[(String, String, Boolean)]()

def flattenSchema(schema: StructType, fieldStructs: ArrayBuffer[(String, String, Boolean)], prefix: String = null): ArrayBuffer[(String, String, Boolean)] = {
  schema.fields.foreach(field => {
    val col = if (prefix == null) field.name else (prefix + "." + field.name)
    field.dataType match {
      case st: StructType => {
        fieldStructs += ((col, field.dataType.typeName, field.nullable))
        flattenSchema(st, fieldStructs, col)
      }
      case _ => {
        fieldStructs += ((col, field.dataType.simpleString, field.nullable))
      }
    }}
  )
  fieldStructs
}

val foo = flattenSchema(actualDF.schema, fieldStructs).toSeq.toDF("field", "type", "nullable")
foo.show(false)

如果您运行上述操作,您应该得到以下内容。

代码语言:javascript
复制
+-------------------------------------+-------+--------+
|field                                |type   |nullable|
+-------------------------------------+-------+--------+
|weight                               |double |true    |
|animal_type                          |string |true    |
|animal_interpretation                |struct |false   |
|animal_interpretation.is_large_animal|boolean|true    |
|animal_interpretation.is_mammal      |boolean|true    |
+-------------------------------------+-------+--------+
票数 0
EN

Stack Overflow用户

发布于 2019-07-16 20:12:46

你可以做这样的事

代码语言:javascript
复制
def flattenSchema(schema: StructType, prefix: String = null) : Seq[(String, String, Boolean)] = {
  schema.fields.flatMap(field => {
    val col = if (prefix == null) field.name else (prefix + "." + field.name)
    field.dataType match {
      case st: StructType => flattenSchema(st, col)
      case _ => Array((col, field.dataType.simpleString, field.nullable))
    }
  })
}

flattenSchema(actualDF.schema).toDF("field", "type", "nullable").show()

希望这能有所帮助!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57063843

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档