Collegamento tra oggetto scala, dataset e dataframe [duplicato]

Sep 28 2020

Ho creato la seguente classe di casi:

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]
)

E analizzo un formato JSON (parte di un HTML) con il framework di gioco.

Finalmente ottengo un Object Ads

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

Voglio salvarlo in un file CSV nel modo seguente:

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") Converto l'oggetto in un elenco di e converto questo elenco in un DataFrame.

Ma ho solo una colonna Value che contiene tutti gli elementi dell'oggetto.

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

Qualcuno ha un'idea per favore? Non capisco davvero come collegare l'oggetto scala con dataset e dataframe. Grazie per l'aiuto.

Risposte

ELinda Sep 28 2020 at 12:37

I commenti sono utili, ma la funzione di appiattimento generico potrebbe non produrre colonne nell'ordine desiderato e / o gestire l'inserimento di elementi dell'array nelle colonne separate.

Supponendo che il tuo file JSON contenga righe come:

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

Se il file è abbastanza coerente e stai già includendo Spark come dipendenza, probabilmente non è necessario utilizzare una libreria separata per analizzare il JSON.

Sarà necessario utilizzare la explodefunzione per gestire il fatto che la colonna "attributo" è un elenco. Utilizza explode_outerinvece la funzione se gli elenchi possono essere vuoti ma desideri preservare i valori delle altre colonne.

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 produrrebbe:

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

Per eseguire l'output come un singolo file CSV nella directory specificata, con intestazioni:

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