¿Cómo imprimir el contenido de RDD?


124

Estoy intentando imprimir el contenido de una colección en la consola Spark.

Tengo un tipo:

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

Y uso el comando:

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

Pero esto está impreso:

res1: org.apache.spark.rdd.RDD [Unidad] = MappedRDD [4] en el mapa en: 19

¿Cómo puedo escribir el RDD en la consola o guardarlo en el disco para poder ver su contenido?


1
¡Hola! ¿Leyó los comentarios sobre la respuesta, aceptados por usted? Parece ser engañoso
dk14

2
@ dk14 estuvo de acuerdo, he reasignado la respuesta aceptada
blue-sky

RDD está siendo relegado como ciudadanos de segunda clase, debe usar DataFrame y el showmétodo.
Thomas Decaux el

Respuestas:


235

Si desea ver el contenido de un RDD, una forma es usar collect():

myRDD.collect().foreach(println)

Sin embargo, esa no es una buena idea cuando el RDD tiene miles de millones de líneas. Use take()para tomar solo unos pocos para imprimir:

myRDD.take(n).foreach(println)

1
Si uso foreach en RDD (que tiene millones de líneas) para escribir el contenido en HDFS como un solo archivo, ¿funcionará sin problemas en el clúster?
Shankar

La razón por la que no estoy usando saveAsTextFileRDD es porque necesito escribir el contenido RDD en más de un archivo, es por eso que estoy usandoforeach
Shankar

Si desea guardar en un solo archivo, puede fusionar su RDD en una partición antes de llamar a saveAsTextFile, pero nuevamente esto puede causar problemas. Creo que la mejor opción es escribir en múltiples archivos en HDFS, luego usar hdfs dfs --getmerge para fusionar los archivos
Oussama

usted dijo que cuando usa foreach en un RDD lo mantendrá en la RAM del controlador, ¿es correcta la declaración? porque lo que entendí es foreach se ejecutará en cada trabajador [cluster] no en el controlador.
Shankar

saveAsTextFile escribirá un archivo por partición, que es lo que desea (varios archivos). De lo contrario, como sugiere Oussama, puede hacer rdd.coalesce (1) .saveAsTextFile () para obtener un archivo. Si el RDD tiene muy pocos tabiques para su gusto, puede intentar rdd.repartition (N) .saveAsTextFile ()
sirena

49

La mapfunción es una transformación , lo que significa que Spark en realidad no evaluará su RDD hasta que ejecute una acción sobre él.

Para imprimirlo, puede usar foreach(que es una acción):

linesWithSessionId.foreach(println)

Para escribirlo en el disco, puede usar una de las saveAs...funciones (aún acciones) de la API RDD


66
Quizás deba mencionarlo collectpara que el RDD pueda imprimirse en la consola.
zsxwing

1
foreachprimero "materializará" el RDD y luego se ejecutará printlnen cada elemento, por collectlo que no es realmente necesario aquí (aunque puede usarlo, por supuesto) ...
fedragon

55
En realidad, sin collect (), antes de foreach, no puedo ver nada en la consola.
Vittorio Cozzolino

3
En realidad, funciona totalmente bien en mi shell Spark, incluso en 1.2.0. Pero creo que sé de dónde viene esta confusión: la pregunta original preguntaba cómo imprimir un RDD en la consola Spark (= shell), así que supuse que ejecutaría un trabajo local, en cuyo caso foreachfunciona bien. Si está ejecutando un trabajo en un clúster y desea imprimir su rdd, entonces debe collect(como lo indican otros comentarios y respuestas) para que se envíe al controlador antes de que printlnse ejecute. Y usar takesegún lo sugerido por Oussama podría ser una buena idea si su RDD es demasiado grande.
fedragon

66
La respuesta anterior es mala. No deberías aceptarlo. Foreach no imprimirá en la consola, imprimirá en sus nodos de trabajo. Si solo tiene un nodo, foreach funcionará. Pero si solo tiene un nodo, ¿por qué está usando la chispa? Simplemente use SQL awk, o Grep, o algo mucho más simple. Así que creo que la única respuesta válida es recoger. Si recolectar es demasiado grande para usted y solo desea una muestra, use las funciones take o head o simillar como se describe a continuación.
eshalev

12

Si está ejecutando esto en un clúster println, no volverá a imprimir en su contexto. Necesita traer los RDDdatos a su sesión. Para hacer esto, puede forzarlo a una matriz local y luego imprimirlo:

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

12

Puede convertir su RDDa DataFrameluego show().

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

Esto mostrará las 20 líneas principales de sus datos, por lo que el tamaño de sus datos no debería ser un problema.

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

1
Creo que esimport spark.implicits._
Ryan Hartman

¿Cuál es la biblioteca que se usó aquí? No puedo detectar toDFni spark.implicits._en alcance de chispa.
Sergii

1

Probablemente hay muchas diferencias arquitectónicas entre myRDD.foreach(println)y myRDD.collect().foreach(println)(no solo 'recoger', sino también otras acciones). Una de las diferencias que vi es que al hacerlo myRDD.foreach(println), la salida será en orden aleatorio. Por ejemplo: si mi rdd proviene de un archivo de texto donde cada línea tiene un número, la salida tendrá un orden diferente. Pero cuando lo hice myRDD.collect().foreach(println), el orden permanece igual que el archivo de texto.


1

En pitón

   linesWithSessionIdCollect = linesWithSessionId.collect()
   linesWithSessionIdCollect

Esto imprimirá todo el contenido del RDD


1
Gracias pero etiqueté esta pregunta con scala no python
blue-sky

1
c.take(10)

y la versión más nueva de Spark mostrará la tabla muy bien.


1

En lugar de escribir cada vez, puedes;

[1] Cree un método de impresión genérico dentro de Spark Shell.

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

[2] O incluso mejor, usando implicits, puedes agregar la función a la clase RDD para imprimir su contenido.

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

Ejemplo de uso:

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

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

Salida:

2
6
4
8

Importante

Esto solo tiene sentido si está trabajando en modo local y con una pequeña cantidad de conjunto de datos. De lo contrario, no podrá ver los resultados en el cliente o quedarse sin memoria debido al resultado del gran conjunto de datos.



0

En la sintaxis de Java:

rdd.collect().forEach(line -> System.out.println(line));
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.