1
votes

Comment sélectionner des clés à partir d'un objet Json {} (type de données complexe) DataFrame dans Spark

J'ai une chaîne json comme:

 java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to org.apache.spark.sql.Row

Je souhaite en créer un DataFrame avec des colonnes DataFrame comme:

val pdf = json.select("restaurants.restaurant.user_rating")
pdf.map{Rrowow => (row.getStruct(0).getString(0))}.show()

Quand je le code comme:

val pdf = json.select("user_rating")

Je n’obtiens qu’une seule colonne user_rating

J'ai approché cette solution la plus votée mais qui ne reçoit toujours que la colonne user_rating : pdf.show()

Je ne sais pas comment le Solution1 fonctionne exactement.

Solution 1 Solution 2

Impossible d'accéder aux colonnes par index car fourni dans Solution2 . Obtention d'une erreur de colonne NoSuchColumn .


Quelle est la meilleure approche possible pour extraire les clés (rating_text, rating_color, ..) et les utiliser comme colonnes dans un DataFrame?

Langue que j'utilise: Scala


J'ai essayé la méthode ci-dessous pour itérer sur chaque Ligne dans DataFrame et analyser en obtenant des colonnes:

rating_text | rating_color | votes | aggregate_rating

Obtenir l'exception ci-dessous à la fonction map :

{"user_rating": {"rating_text": "Excellent", "rating_color": "3F7E00", "votes": "778", "aggregate_rating": "4.5"}}


4 commentaires

Bonjour @Harshvardhan, réessayez cette fois en utilisant json.select ("user_rating. *")


Une colonne contient-elle une chaîne json ou un fichier contenant des lignes json?


@baitmbarek J'ai eu org.apache.spark.sql.AnalysisException: ne peut que développer en étoile les types de données struct Exception en essayant avec '. *'


@Salim Complete json est dans un fichier, dont "user_rating" est un sous-json String


3 Réponses :


1
votes

Vous pouvez analyser une colonne contenant une chaîne JSON et créer une trame de données contenant toutes les colonnes du JSON. Voici un exemple -

    df.map{ row =>
      (row.getStruct(0).getString(0))
    }.show()

    //Used getStruct(index) because the data type is a complex class. for ordinary values you can use getString, getLong etc

Résultat -

    //file contains - {"user_rating": {"rating_text": "Excellent", "rating_color": "3F7E00", "votes": "778", "aggregate_rating": "4.5"}}
    val df = spark.read.json("path to test.txt")
    df.select("user_rating.rating_text").show()

Si le json est sur un fichier, vous pouvez simplement le lire par p >

+--------------------+-----------+------------+-----+----------------+
|         user_rating|rating_text|rating_color|votes|aggregate_rating|
+--------------------+-----------+------------+-----+----------------+
|{"rating_text": "...|  Excellent|      3F7E00|  778|             4.5|
+--------------------+-----------+------------+-----+----------------+

Vous pouvez lire les données de l'objet Row en utilisant un index comme,

    val jsonData = """{"rating_text": "Excellent", "rating_color": "3F7E00", "votes": "778", "aggregate_rating": "4.5"}"""

    val schema = {StructType(
      List(
        StructField("rating_text", StringType, nullable = false),
        StructField("rating_color", StringType, nullable = false),
        StructField("votes", StringType, nullable = false),
        StructField("aggregate_rating", StringType, nullable = false)
      ))}

    val df = spark.createDataset(Seq(jsonData)).toDF("user_rating")
    val dfWithParsedJson = df.withColumn("json_data",from_json($"user_rating",schema))

    dfWithParsedJson.select($"user_rating",$"json_data.rating_text", $"json_data.rating_color",$"json_data.votes",$"json_data.aggregate_rating").show()

Je vous recommande vivement en utilisant un schéma pour lire et utiliser json. Cela vous évitera des tonnes d'erreurs d'exécution et beaucoup plus rapidement.


5 commentaires

Merci beaucoup pour la solution. Mais existe-t-il un moyen dynamique d'obtenir des colonnes? Où les noms de colonnes ne sont pas connus à l'avance pour construire le schéma? Comme n'importe quel moyen d'accéder à ces colonnes via un index!


Oui, la dynamique est possible. Laisse moi faire un exemple


Bien sûr merci :)


J'ai mis à jour la réponse selon vos besoins. Veuillez accepter la réponse si cela fonctionne.


Obtenir ClassCastException. Veuillez consulter la question mise à jour. J'ai collé le journal là-bas



1
votes

J'ai le travail. Fondamentalement, ce que je recherchais était la fonction exploser . Ce qui renvoie une ligne pour chaque élément de la colonne.


0 commentaires

0
votes


0 commentaires