【问题标题】:Link between scala object, dataset and dataframe [duplicate]scala对象,数据集和数据框之间的链接[重复]
【发布时间】:2021-01-13 08:20:29
【问题描述】:

我创建了以下案例类:

case class Data(ads:Option[Ads])

case class Ads(subject: Option[String]
           , body:Option[String]
           , price:Option[Int]
           , location:Option[Location]
           , attribut:Option[Seq[Attribut]]
 )

case class Location(city:Option[String]
                , zipcode:Option[String])

case class Attribut(key_label:Option[String]
                , value_label:Option[String]
)

我使用播放框架解析 JSON 格式(HTML 的一部分)。

我终于得到了一个对象广告

JsSuccess(Ads(Some("Subject"), SOme("Body"), Some(Price), Some(Location(Some("City"), Some("Zipcode")), Some(Attribut("key_label", "value_label")) 

我想通过以下方式将其保存在 CSV 文件中:

Subject   Body           Price   City  Zipcode  Key_Label  Value_Label
Play      Playing games  532     Geneve 95      GEN        Gen2

我将对象转换为Ads(Some("Subject"), Some("Body"), Some(Price), Some(Location(Some("City"), Some("Zipcode")), Some(Attribut("key_label", "value_label") 的列表并将此列表转换为DataFrame。

但我只有一列 Value 包含对象的所有元素。

    Value
    (Some("Subject"), SOme("Body"), Some(Price), Some(Location(Some("City"), Some("Zipcode")), Some(Attribut("key_label", "value_label")

请问有人有想法吗? 我真的不明白如何将 scala 对象与数据集和数据框链接起来。 感谢您的帮助。

【问题讨论】:

  • 您是如何将List 转换为DataFrame 的?另外,我相信编写本地 CSV 文件而不是提取 Spark 会有更好的选择。
  • 不清楚为什么要使用带有单个 JSON 文件的 Spark。如果你这样做 df.printSchema() 它可能表明它有单列 Value 这是一个结构。如果是,您只需将其拆包/展平即可。您可以使用.withColunn(...,...) 解包或如上例中那样展平
  • 感谢您的回答。我终于认为没有必要使用Spark。我想要转换 JsSuccess(Ads(Some("Subject"), SOme("Body"), Some(Price), Some(Location(Some("City"), Some("Zipcode")), Some(Attribut(将“key_label”、“value_label”)) 转换为 7 列的 CSV 文件:主题、正文、价格、城市、邮政编码、Key_Label 和 Key_value。有什么想法吗?
  • 我确实喜欢这样:implicit class CSVWrapper(val prod: Product) extends AnyVal { def toCSV: String = prod.productIterator.map{ case p: Product => p.toCSV case rest => rest }.mkString("|") }

标签: json scala dataframe apache-spark playframework


【解决方案1】:

注释很有帮助,但通用展平功能可能无法按所需顺序输出列,和/或无法处理将数组元素放入各自单独的列中。

假设您的 JSON 文件包含以下行:

{"ads": {"subject": "abc", "body": "doing something", "price": 13, "location": {"city": "Houston", "zipcode": 39014}, "attribut": [{"key_label": "a", "value_label": "b"}]}}

如果文件相当一致并且您已经将 Spark 作为依赖项包含在内,那么您可能不需要使用单独的库来解析 JSON。

您将需要使用explode 函数来处理“属性”列是一个列表这一事实。如果列表可能为空但您想保留其他列的值,请改用 explode_outer 函数。

import org.apache.spark.sql.functions._
// assuming spark is the Spark Session
val df = spark.read.json("mydata.json")

val df1 = df.select(col("ads.subject").alias("Subject"), col("ads.body").alias("Body"),
          col("ads.location.city").alias("City"), col("ads.location.zipcode").alias("Zipcode"),
          explode(col("ads.attribut")))

val resultDF = df1.select(col("Subject"), col("Body"), col("City"), col("Zipcode"),
               col("col.key_label"), col("col.value_label"))

resultDF.show 会输出:

+-------+---------------+-------+-------+---------+-----------+
|Subject|           Body|   City|Zipcode|key_label|value_label|
+-------+---------------+-------+-------+---------+-----------+
|    abc|doing something|Houston|  39014|        a|          b|
+-------+---------------+-------+-------+---------+-----------+

在指定目录中输出为单个 CSV 文件,带有标题:

resultDF.repartition(1).write.option("header", "true").csv("/tmp/my-output-dir/")

【讨论】:

  • 感谢您的回答。我终于认为没有必要使用Spark。我想要转换 JsSuccess(Ads(Some("Subject"), SOme("Body"), Some(Price), Some(Location(Some("City"), Some("Zipcode")), Some(Attribut(将“key_label”、“value_label”)) 转换为 7 列的 CSV 文件:主题、正文、价格、城市、邮政编码、Key_Label 和 Key_value。有什么想法吗?
猜你喜欢
  • 2018-08-31
  • 2021-02-18
  • 1970-01-01
  • 2021-09-02
  • 2020-04-19
  • 2018-11-30
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多