Come stampare il contenuto di RDD?


124

Sto tentando di stampare il contenuto di una raccolta sulla console Spark.

Ho un tipo:

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

E io uso il comando:

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

Ma questo è stampato:

res1: org.apache.spark.rdd.RDD [Unit] = MappedRDD [4] alla mappa a: 19

Come posso scrivere l'RDD sulla console o salvarlo su disco in modo da poter visualizzare il suo contenuto?


1
Ciao! hai letto i commenti alla risposta, da te accettati? Sembra essere fuorviante
dk14

2
@ dk14 d'accordo, ho riassegnato la risposta accettata
cielo blu

RDD vengono relegati come cittadini di seconda classe, dovresti usare DataFrame e il showmetodo.
Thomas Decaux

Risposte:


235

Se vuoi visualizzare il contenuto di un RDD, un modo è usare collect():

myRDD.collect().foreach(println)

Non è una buona idea, però, quando l'RDD ha miliardi di linee. Utilizzare take()per prendere solo alcuni per la stampa:

myRDD.take(n).foreach(println)

1
se uso foreach su RDD (che ha milioni di righe) per scrivere il contenuto in HDFS come singolo file, funzionerà senza problemi sul cluster?
Shankar

Il motivo per cui non utilizzo saveAsTextFilesu RDD è che ho bisogno di scrivere il contenuto RDD in più di un file, ecco perché sto usandoforeach
Shankar

Se vuoi salvare in un singolo file, puoi unire il tuo RDD in una partizione prima di chiamare saveAsTextFile, ma ancora una volta ciò potrebbe causare problemi. Penso che l'opzione migliore sia scrivere in più file in HDFS, quindi utilizzare hdfs dfs --getmerge per unire i file
Oussama

hai detto che quando si usa foreach su un RDD lo persisterà nella RAM del driver, la dichiarazione è corretta? perché quello che ho capito è che foreach verrà eseguito su ogni worker [cluster] non sul driver.
Shankar

saveAsTextFile scriverà un file per partizione, che è quello che vuoi (più file). Altrimenti, come suggerisce Oussama, puoi eseguire rdd.coalesce (1) .saveAsTextFile () per ottenere un file. Se l'RDD ha troppe poche partizioni per i tuoi gusti, puoi provare rdd.repartition (N) .saveAsTextFile ()
nebbia

49

La mapfunzione è una trasformazione , il che significa che Spark non valuterà effettivamente il tuo RDD fino a quando non esegui un'azione su di esso.

Per stamparlo, puoi usare foreach(che è un'azione):

linesWithSessionId.foreach(println)

Per scriverlo su disco è possibile utilizzare una delle saveAs...funzioni (ancora azioni) dall'API RDD


6
Forse è necessario menzionare in collectmodo che l'RDD possa essere stampato nella console.
zsxwing

1
foreachstesso prima "materializzerà" l'RDD e poi verrà eseguito printlnsu ogni elemento, quindi collectnon è realmente necessario qui (anche se puoi usarlo, ovviamente) ...
fedragon

5
In realtà senza collect (), prima di foreach, non riesco a vedere nulla su console.
Vittorio Cozzolino

3
In realtà funziona perfettamente nella mia shell Spark, anche nella 1.2.0. Ma penso di sapere da dove proviene questa confusione: la domanda originale chiedeva come stampare un RDD sulla console Spark (= shell), quindi ho pensato che avrebbe eseguito un lavoro locale, nel qual caso foreachfunziona bene. Se stai eseguendo un lavoro su un cluster e vuoi stampare il tuo rdd allora dovresti collect(come sottolineato da altri commenti e risposte) in modo che venga inviato al driver prima che printlnvenga eseguito. E usare takecome suggerito da Oussama potrebbe essere una buona idea se il tuo RDD è troppo grande.
fedragon

6
La risposta sopra è cattiva. Dovresti non accettarlo. Foreach non stamperà sulla console, ma sui tuoi nodi di lavoro. Se hai un solo nodo, foreach funzionerà. Ma se hai un solo nodo, perché stai usando Spark? Basta usare SQL awk, o Grep, o qualcosa di molto più semplice. Quindi penso che l'unica risposta valida sia raccogliere. Se la raccolta è troppo grande per te e desideri solo un campione, usa take o funzioni head o simili come descritto di seguito.
Eshalev

12

Se lo stai eseguendo su un cluster println, non verrà stampato nel tuo contesto. Devi portare i RDDdati alla tua sessione. Per fare ciò puoi forzarlo sull'array locale e quindi stamparlo:

linesWithSessionId.toArray().foreach(line => println(line))

12

Puoi convertire il tuo RDDin un DataFramepoi show()esso.

// 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()

Questo mostrerà le prime 20 righe dei tuoi dati, quindi la dimensione dei tuoi dati non dovrebbe essere un problema.

+------+---+                                                                    
|    _1| _2|
+------+---+
| apple|  1|
|banana|  2|
|orange| 17|
+------+---+

1
Penso che siaimport spark.implicits._
Ryan Hartman

Qual è la libreria è stata utilizzata qui? Non riesco a rilevare né toDFspark.implicits._nel cannocchiale Spark.
Sergii

1

Ci sono probabilmente molte differenze architettoniche tra myRDD.foreach(println)e myRDD.collect().foreach(println)(non solo "collect", ma anche altre azioni). Una delle differenze che ho visto è che quando lo faccio myRDD.foreach(println), l'output sarà in ordine casuale. Ad esempio: se il mio rdd proviene da un file di testo in cui ogni riga ha un numero, l'output avrà un ordine diverso. Ma quando l'ho fatto myRDD.collect().foreach(println), l'ordine rimane esattamente come il file di testo.


1

In pitone

   linesWithSessionIdCollect = linesWithSessionId.collect()
   linesWithSessionIdCollect

Questo stamperà tutti i contenuti dell'RDD


1
Grazie ma ho contrassegnato questa domanda con scala not python
blue-sky

1
c.take(10)

e la versione più recente di Spark mostrerà bene la tabella.


1

Invece di digitare ogni volta, puoi;

[1] Crea un metodo di stampa generico all'interno di Spark Shell.

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

[2] O ancora meglio, usando gli impliciti, puoi aggiungere la funzione alla classe RDD per stamparne il contenuto.

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

Utilizzo di esempio:

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

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

Produzione:

2
6
4
8

Importante

Ciò ha senso solo se si lavora in modalità locale e con una piccola quantità di set di dati. In caso contrario, non sarai in grado di vedere i risultati sul client o esaurirai la memoria a causa del grande risultato del set di dati.



0

Nella sintassi java:

rdd.collect().forEach(line -> System.out.println(line));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.