Wie drucke ich den Inhalt von RDD?

124

Ich versuche, den Inhalt einer Sammlung auf der Spark-Konsole zu drucken.

Ich habe einen Typ:

linesWithSessionId: org.apache.spark.rdd.RDD[String] = FilteredRDD[3]

Und ich benutze den Befehl:

scala> linesWithSessionId.map(line => println(line))

Aber das ist gedruckt:

res1: org.apache.spark.rdd.RDD [Unit] = MappedRDD [4] auf der Karte um: 19

Wie kann ich das RDD auf die Konsole schreiben oder auf der Festplatte speichern, um den Inhalt anzuzeigen?

blauer Himmel
quelle
1
Hallo! Haben Sie die von Ihnen akzeptierten Kommentare zu der Antwort gelesen? Es scheint irreführend zu sein
dk14
2
@ dk14 stimmte zu, ich habe akzeptierte Antwort neu zugewiesen
blue-sky
RDD werden als Bürger zweiter Klasse abgestiegen, Sie sollten DataFrame und die showMethode verwenden.
Thomas Decaux

Antworten:

235

Wenn Sie den Inhalt einer RDD anzeigen möchten, können Sie Folgendes verwenden collect():

myRDD.collect().foreach(println)

Das ist jedoch keine gute Idee, wenn die RDD Milliarden von Leitungen hat. Verwenden Sie take()zum Ausdrucken nur wenige:

myRDD.take(n).foreach(println)
Oussama
quelle
1
Wenn ich foreach auf RDD (mit Millionen von Zeilen) verwende, um den Inhalt als einzelne Datei in HDFS zu schreiben, funktioniert es dann ohne Probleme im Cluster?
Shankar
Der Grund, warum ich nicht saveAsTextFileauf RDD verwende, ist, dass ich den RDD-Inhalt in mehr als eine Datei schreiben muss. Deshalb verwende ichforeach
Shankar
Wenn Sie in einer einzelnen Datei speichern möchten, können Sie Ihre RDD vor dem Aufruf von saveAsTextFile zu einer Partition zusammenführen. Dies kann jedoch wiederum zu Problemen führen. Ich denke, die beste Option ist, in HDFS mehrere Dateien zu schreiben und dann hdfs dfs --getmerge zu verwenden, um die Dateien zusammenzuführen
Oussama
Sie sagten, wenn foreach auf einem RDD verwendet wird, bleibt es im RAM des Treibers erhalten. Ist die Aussage korrekt? weil das, was ich verstanden habe, foreach auf jedem Worker [Cluster] läuft, nicht auf dem Treiber.
Shankar
saveAsTextFile schreibt eine Datei pro Partition, wie Sie möchten (mehrere Dateien). Andernfalls können Sie, wie Oussama vorschlägt, rdd.coalesce (1) .saveAsTextFile () ausführen, um eine Datei abzurufen. Wenn das RDD zu wenige Partitionen für Ihren Geschmack hat, können Sie rdd.repartition (N) .saveAsTextFile ()
Nebelhorn
49

Die mapFunktion ist eine Transformation . Dies bedeutet, dass Spark Ihre RDD erst dann auswertet, wenn Sie eine Aktion darauf ausführen .

Zum Drucken können Sie Folgendes verwenden foreach(was eine Aktion ist):

linesWithSessionId.foreach(println)

Um es auf die Festplatte zu schreiben, können Sie eine der saveAs...Funktionen (Standbildaktionen) der RDD-API verwenden

Fedragon
quelle
6
Möglicherweise müssen Sie erwähnen, collectdamit das RDD in der Konsole gedruckt werden kann.
Zsxwing
1
foreachselbst wird zuerst die RDD "materialisieren" und dann printlnauf jedem Element ausgeführt, wird also collecthier nicht wirklich benötigt (obwohl Sie es natürlich verwenden können) ...
fedragon
5
Eigentlich kann ich ohne collect () vor foreach nichts auf der Konsole sehen.
Vittorio Cozzolino
3
Eigentlich funktioniert es in meiner Spark-Shell ganz gut, sogar in 1.2.0. Aber ich glaube, ich weiß, woher diese Verwirrung kommt: In der ursprünglichen Frage wurde gefragt, wie eine RDD auf die Spark-Konsole (= Shell) gedruckt werden soll, sodass ich davon ausging, dass er einen lokalen Job ausführen würde. In diesem Fall foreachfunktioniert dies einwandfrei. Wenn Sie einen Job in einem Cluster ausführen und Ihre Festplatte drucken möchten, sollten Sie collect(wie in anderen Kommentaren und Antworten angegeben) vor der printlnAusführung an den Treiber gesendet werden . Und takewenn Sie Ihre RDD zu groß verwenden, ist es möglicherweise eine gute Idee, sie wie von Oussama vorgeschlagen zu verwenden.
Fedragon
6
Die obige Antwort ist schlecht. Sie sollten es nicht akzeptieren. Foreach druckt nicht auf der Konsole, sondern auf Ihren Worker-Knoten. Wenn Sie nur einen Knoten haben, funktioniert foreach. Aber wenn Sie nur einen Knoten haben, warum verwenden Sie dann Funken? Verwenden Sie einfach SQL awk oder Grep oder etwas viel Einfacheres. Ich denke, die einzig gültige Antwort ist Sammeln. Wenn das Sammeln für Sie zu groß ist und Sie nur ein Beispiel möchten, verwenden Sie die unten beschriebenen Funktionen take oder head oder simillar.
Eshalev
12

Wenn Sie dies in einem Cluster ausführen, printlnwird nicht in Ihren Kontext zurückgedruckt. Sie müssen die RDDDaten zu Ihrer Sitzung bringen. Dazu können Sie es in ein lokales Array zwingen und dann ausdrucken:

linesWithSessionId.toArray().foreach(line => println(line))
Noah
quelle
12

Sie können Ihre RDDin eine DataFramedann show()es konvertieren .

// For implicit conversion from RDD to DataFrame
import spark.implicits._

fruits = sc.parallelize([("apple", 1), ("banana", 2), ("orange", 17)])

// convert to DF then show it
fruits.toDF().show()

Dies zeigt die obersten 20 Zeilen Ihrer Daten an, sodass die Größe Ihrer Daten kein Problem darstellen sollte.

+------+---+                                                                    
|    _1| _2|
+------+---+
| apple|  1|
|banana|  2|
|orange| 17|
+------+---+
Wesam
quelle
1
Ich denke es istimport spark.implicits._
Ryan Hartman
Was ist die Bibliothek wurde hier verwendet? Ich kann weder toDFnoch spark.implicits._im Funkenbereich erkennen.
Sergii
1

Es gibt wahrscheinlich viele architektonische Unterschiede zwischen myRDD.foreach(println)und myRDD.collect().foreach(println)(nicht nur "sammeln", sondern auch andere Aktionen). Einer der Unterschiede, die ich gesehen habe, ist myRDD.foreach(println), dass die Ausgabe in zufälliger Reihenfolge erfolgt. Zum Beispiel: Wenn meine Festplatte aus einer Textdatei stammt, in der jede Zeile eine Nummer hat, hat die Ausgabe eine andere Reihenfolge. Aber wenn ich das getan habe myRDD.collect().foreach(println), bleibt die Reihenfolge genauso wie die Textdatei.

Karan Gupta
quelle
1

In Python

   linesWithSessionIdCollect = linesWithSessionId.collect()
   linesWithSessionIdCollect

Dadurch wird der gesamte Inhalt der RDD ausgedruckt

Niranjan Molkeri
quelle
1
Danke, aber ich habe diese Frage mit scala not python
blue-sky
1
c.take(10)

und Spark neuere Version wird Tabelle schön zeigen.

Harvey
quelle
1

Anstatt jedes Mal zu tippen, können Sie;

[1] Erstellen Sie eine generische Druckmethode in Spark Shell.

def p(rdd: org.apache.spark.rdd.RDD[_]) = rdd.foreach(println)

[2] Oder noch besser: Mit impliziten Elementen können Sie die Funktion der RDD-Klasse hinzufügen, um deren Inhalt zu drucken.

implicit class Printer(rdd: org.apache.spark.rdd.RDD[_]) {
    def print = rdd.foreach(println)
}

Anwendungsbeispiel:

val rdd = sc.parallelize(List(1,2,3,4)).map(_*2)

p(rdd) // 1
rdd.print // 2

Ausgabe:

2
6
4
8

Wichtig

Dies ist nur sinnvoll, wenn Sie im lokalen Modus und mit einer kleinen Datenmenge arbeiten. Andernfalls können Sie die Ergebnisse entweder nicht auf dem Client sehen oder haben aufgrund des großen Dataset-Ergebnisses nicht genügend Arbeitsspeicher.

noego
quelle
0

Sie können auch als Datei speichern: rdd.saveAsTextFile("alicia.txt")

Thomas Decaux
quelle
0

In der Java-Syntax:

rdd.collect().forEach(line -> System.out.println(line));
ForeverLearner
quelle