【问题标题】:Spark map dataframe using the dataframe's schema使用数据框架构的 Spark 地图数据框
【发布时间】:2016-05-27 14:06:12
【问题描述】:

我有一个从 JSON 对象创建的数据框。我可以查询这个数据框并将其写入 parquet。

由于我推断架构,我不一定知道数据框中的内容。

有没有办法将列名取出或使用自己的架构映射数据框?

// The results of SQL queries are DataFrames and support all the normal  RDD operations.
// The columns of a row in the result can be accessed by field index:
df.map(t => "Name: " + t(0)).collect().foreach(println)

// or by field name:
df.map(t => "Name: " + t.getAs[String]("name")).collect().foreach(println)

// row.getValuesMap[T] retrieves multiple columns at once into a Map[String, T]
df.map(_.getValuesMap[Any](List("name", "age"))).collect().foreach(println)
// Map("name" -> "Justin", "age" -> 19)

我想做类似的事情

df.map (_.getValuesMap[Any](ListAll())).collect().foreach(println)
// Map ("name" -> "Justin", "age" -> 19, "color" -> "red")

不知道列的实际数量或名称。

【问题讨论】:

    标签: scala apache-spark apache-spark-sql


    【解决方案1】:

    好吧,你可以,但结果相当无用:

    val df = Seq(("Justin", 19, "red")).toDF("name", "age", "color")
    
    def getValues(row: Row, names: Seq[String]) = names.map(
      name => name -> row.getAs[Any](name)
    ).toMap
    
    val names = df.columns
    df.rdd.map(getValues(_, names)).first
    
    // scala.collection.immutable.Map[String,Any] = 
    //   Map(name -> Justin, age -> 19, color -> red)
    

    要获得真正有用​​的东西,需要在 SQL 类型和 Scala 类型之间进行适当的映射。在简单的情况下并不难,但在一般情况下很难。例如,有一个内置类型可用于表示任意struct。这可以使用一点元编程来完成,但可以说不值得大惊小怪。

    【讨论】:

      【解决方案2】:

      您可以使用隐式编码器并在 DataFrame 本身上执行映射:

      implicit class DataFrameEnhancer(df: DataFrame) extends Serializable {
          implicit val encoder = RowEncoder(df.schema)
      
          implicit def mapNameAndAge(): DataFrame = {
             df.map(row => (row.getAs[String]("name") -> row.getAs[Int]("age")))
          }
      }
      

      然后在你的数据框上调用它:

      val df = Seq(("Justin", 19, "red")).toDF("name", "age", "color")
      df.mapNameAndAge().first
      

      这样,您不必将 DataFrame 转换为 RDD(在某些情况下,您不想从磁盘加载整个 DF,只加载一些列,但是 RDD 转换迫使您这样做无论如何。另外,您使用的是 Encoder 而不是 Kryo(或其他 Java SerDes),速度要快得多。

      希望对你有帮助:-)

      【讨论】:

        猜你喜欢
        • 2021-12-15
        • 1970-01-01
        • 2020-02-13
        • 2021-11-11
        • 2021-09-21
        • 2022-01-18
        • 2020-08-12
        • 1970-01-01
        • 2022-11-11
        相关资源
        最近更新 更多