J'ai le dataframe Spark suivant qui est créé dynamiquement:
val sf1 = StructField("name", StringType, nullable = true)
val sf2 = StructField("sector", StringType, nullable = true)
val sf3 = StructField("age", IntegerType, nullable = true)
val fields = List(sf1,sf2,sf3)
val schema = StructType(fields)
val row1 = Row("Andy","aaa",20)
val row2 = Row("Berta","bbb",30)
val row3 = Row("Joe","ccc",40)
val data = Seq(row1,row2,row3)
val df = spark.createDataFrame(spark.sparkContext.parallelize(data), schema)
df.createOrReplaceTempView("people")
val sqlDF = spark.sql("SELECT * FROM people")
Maintenant, je dois itérer chaque ligne et colonne dans sqlDF
pour imprimer chaque colonne, voici ma tentative:
sqlDF.foreach { row =>
row.foreach { col => println(col) }
}
row
est de type Row
, mais n'est pas itérable, c'est pourquoi ce code génère une erreur de compilation dans row.foreach
. Comment itérer chaque colonne dans Row
?
Vous pouvez convertir Row
en Seq
avec toSeq
. Une fois passé à Seq
, vous pouvez le parcourir comme d'habitude avec foreach
, map
ou ce dont vous avez besoin
sqlDF.foreach { row =>
row.toSeq.foreach{col => println(col) }
}
Sortie:
Berta
bbb
30
Joe
Andy
aaa
20
ccc
40
Considérez que vous avez une Dataframe
comme ci-dessous
val df = Seq(
("Andy","aaa", 20),
("Berta","bbb", 30),
("Joe","ccc", 40)).toDF("name","sector","age")
Pour boucler votre Dataframe et extraire les éléments du Dataframe , df.foreach
ne vous aidera pas directement. Pour le mettre en œuvre, vous pouvez choisir l'une des approches ci-dessous.
Approche 1 - Boucle avec rdd
Utilisez rdd.collect
en plus de votre Dataframe . La variable row
contiendra chaque ligne de Dataframe de type rdd
. Pour obtenir chaque élément d'une ligne, utilisez row.mkString(",")
qui contiendra la valeur de chaque ligne sous forme de valeurs séparées par des virgules. En utilisant la fonction split
(fonction intégrée), vous pouvez accéder à chaque valeur de colonne de rdd
rangée avec index.
for (row <- df.rdd.collect)
{
var name = row.mkString(",").split(",")(0)
var sector = row.mkString(",").split(",")(1)
var age = row.mkString(",").split(",")(2)
}
Approche 2 - Utiliser où et sélectionner
Vous pouvez directement utiliser where
et select
qui effectuera une boucle interne et trouvera les données. Puisqu'il ne devrait pas lancer l'exception Index hors limite, une condition if est utilisée
if(df.where($"name" === "Andy").select(col("name")).collect().length >= 1)
name = df.where($"name" === "Andy").select(col("name")).collect()(0).get(0).toString
Approche 3 - Utilisation de tables temporaires
Vous pouvez enregistrer une image de données comme étant tentante, qui sera stockée dans la mémoire de spark. Ensuite, vous pouvez utiliser une requête select comme une autre base de données pour interroger les données, puis collecter et enregistrer dans une variable.
df.registerTempTable("student")
name = sqlContext.sql("select name from student where name='Andy'").collect()(0).toString().replace("[","").replace("]","")
Vous devriez utiliser mkString
sur votre Row
:
sqlDF.foreach { row =>
println(row.mkString(","))
}
Mais notez que cela sera imprimé dans les machines virtuelles JVM des exécuteurs, donc normalement, vous ne verrez pas la sortie (sauf si vous travaillez avec maître = local)
sqlDF.foreach
ne fonctionne pas pour moi mais l'approche 1 de @Sarath Avanavu answer fonctionne, mais elle jouait aussi parfois avec l'ordre des enregistrements.
J'ai trouvé un autre moyen qui fonctionne
df.collect().foreach { row =>
println(row.mkString(","))
}