web-dev-qa-db-fra.com

Comment convertir pyspark.rdd.PipelinedRDD en trame de données sans utiliser la méthode collect () dans Pyspark?

J'ai pyspark.rdd.PipelinedRDD (Rdd1). quand je fais Rdd1.collect(), ça donne un résultat comme ci-dessous.

 [(10, {3: 3.616726727464709, 4: 2.9996439803387602, 5: 1.6767412921625855}),
 (1, {3: 2.016527311459324, 4: -1.5271512313750577, 5: 1.9665475696370045}),
 (2, {3: 6.230272144805092, 4: 4.033642544526678, 5: 3.1517805604906313}),
 (3, {3: -0.3924680103722977, 4: 2.9757316477407443, 5: -1.5689126834176417})]

Maintenant, je veux convertir pyspark.rdd.PipelinedRDD en trame de données sans utiliser la méthode collect ()

Ma trame de données finale devrait être comme ci-dessous.df.show () devrait être comme:

+----------+-------+-------------------+
|CId       |IID    |Score              |
+----------+-------+-------------------+
|10        |4      |2.9996439803387602 |
|10        |5      |1.6767412921625855 |
|10        |3      |3.616726727464709  |
|1         |4      |-1.5271512313750577|
|1         |5      |1.9665475696370045 |
|1         |3      |2.016527311459324  |
|2         |4      |4.033642544526678  |
|2         |5      |3.1517805604906313 |
|2         |3      |6.230272144805092  |
|3         |4      |2.9757316477407443 |
|3         |5      |-1.5689126834176417|
|3         |3      |-0.3924680103722977|
+----------+-------+-------------------+

Je peux réaliser cette conversion en rdd en appliquant ensuite collect (), itération et enfin Data frame.

mais maintenant je veux convertir pyspark.rdd.PipelinedRDD (RDD1) en trame de données sans utiliser de méthode collect ().

s'il vous plaît laissez-moi savoir comment y parvenir?

6
Sai

Vous voulez faire deux choses ici: 1. aplatissez vos données 2. mettez-les dans un cadre de données

Une façon de le faire est la suivante:

Commençons par aplatir le dictionnaire:

rdd2 = Rdd1.flatMapValues(lambda x : [ (k, x[k]) for k in x.keys()])

Lors de la collecte des données, vous obtenez quelque chose comme ceci:

[(10, (3, 3.616726727464709)), (10, (4, 2.9996439803387602)), ...

Ensuite, nous pouvons formater les données et les transformer en trame de données:

rdd2.map(lambda x : (x[0], x[1][0], x[1][1]))\
    .toDF(("CId", "IID", "Score"))\
    .show()

ce qui vous donne ceci:

+---+---+-------------------+
|CId|IID|              Score|
+---+---+-------------------+
| 10|  3|  3.616726727464709|
| 10|  4| 2.9996439803387602|
| 10|  5| 1.6767412921625855|
|  1|  3|  2.016527311459324|
|  1|  4|-1.5271512313750577|
|  1|  5| 1.9665475696370045|
|  2|  3|  6.230272144805092|
|  2|  4|  4.033642544526678|
|  2|  5| 3.1517805604906313|
|  3|  3|-0.3924680103722977|
|  3|  4| 2.9757316477407443|
|  3|  5|-1.5689126834176417|
+---+---+-------------------+
5
Oli

Il existe une solution encore plus simple et plus élégante évitant python expressions lambda comme dans la réponse @oli qui repose sur spark DataFrames explode qui correspond parfaitement à vos besoins. Il devrait aussi être plus rapide car il n'est pas nécessaire d'utiliser deux fois python lambda. Voir ci-dessous:

from pyspark.sql.functions import explode

# dummy data
data = [(10, {3: 3.616726727464709, 4: 2.9996439803387602, 5: 1.6767412921625855}),
        (1, {3: 2.016527311459324, 4: -1.5271512313750577, 5: 1.9665475696370045}),
        (2, {3: 6.230272144805092, 4: 4.033642544526678, 5: 3.1517805604906313}),
        (3, {3: -0.3924680103722977, 4: 2.9757316477407443, 5: -1.5689126834176417})]

# create your rdd
rdd = sc.parallelize(data)

# convert to spark data frame
df = rdd.toDF(["CId", "Values"])

# use explode
df.select("CId", explode("Values").alias("IID", "Score")).show()

+---+---+-------------------+
|CId|IID|              Score|
+---+---+-------------------+
| 10|  3|  3.616726727464709|
| 10|  4| 2.9996439803387602|
| 10|  5| 1.6767412921625855|
|  1|  3|  2.016527311459324|
|  1|  4|-1.5271512313750577|
|  1|  5| 1.9665475696370045|
|  2|  3|  6.230272144805092|
|  2|  4|  4.033642544526678|
|  2|  5| 3.1517805604906313|
|  3|  3|-0.3924680103722977|
|  3|  4| 2.9757316477407443|
|  3|  5|-1.5689126834176417|
+---+---+-------------------+
2
pansen

Voici comment le faire avec scala

  val Rdd1 = spark.sparkContext.parallelize(Seq(
    (10, Map(3 -> 3.616726727464709, 4 -> 2.9996439803387602, 5 -> 1.6767412921625855)),
    (1, Map(3 -> 2.016527311459324, 4 -> -1.5271512313750577, 5 -> 1.9665475696370045)),
    (2, Map(3 -> 6.230272144805092, 4 -> 4.033642544526678, 5 -> 3.1517805604906313)),
    (3, Map(3 -> -0.3924680103722977, 4 -> 2.9757316477407443, 5 -> -1.5689126834176417))
  ))

  val x = Rdd1.flatMap(x => (x._2.map(y => (x._1, y._1, y._2))))
         .toDF("CId", "IId", "score")

Production:

+---+---+-------------------+
|CId|IId|score              |
+---+---+-------------------+
|10 |3  |3.616726727464709  |
|10 |4  |2.9996439803387602 |
|10 |5  |1.6767412921625855 |
|1  |3  |2.016527311459324  |
|1  |4  |-1.5271512313750577|
|1  |5  |1.9665475696370045 |
|2  |3  |6.230272144805092  |
|2  |4  |4.033642544526678  |
|2  |5  |3.1517805604906313 |
|3  |3  |-0.3924680103722977|
|3  |4  |2.9757316477407443 |
|3  |5  |-1.5689126834176417|
+---+---+-------------------+ 

J'espère que vous pourrez vous convertir à pyspark.

1
Shankar Koirala

Assurez-vous qu'une session spark est créée en premier:

sc = SparkContext()
spark = SparkSession(sc)

J'ai trouvé cette réponse lorsque j'essayais de résoudre ce problème exact.
l'objet 'PipelinedRDD' n'a pas d'attribut 'toDF' dans PySpark

0
Zhi Yong Lee