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.
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"}}
3 Réponses :
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.
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
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.
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