Bagaimana cara mencetak konten RDD?


124

Saya mencoba mencetak konten koleksi ke konsol Spark.

Saya punya tipe:

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

Dan saya menggunakan perintah:

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

Tapi ini dicetak:

res1: org.apache.spark.rdd.RDD [Unit] = MappedRDD [4] di peta pada: 19

Bagaimana cara menulis RDD ke konsol atau menyimpannya ke disk sehingga saya dapat melihat isinya?


1
Hai! apakah Anda membaca komentar pada jawaban, diterima oleh Anda? Tampaknya menyesatkan
dk14

2
@ dk14 setuju, saya telah menetapkan kembali jawaban yang diterima
langit biru

RDD diturunkan sebagai warga kelas dua, Anda harus menggunakan DataFrame dan showmetode.
Thomas Decaux

Jawaban:


235

Jika Anda ingin melihat konten RDD, salah satu caranya adalah dengan menggunakan collect():

myRDD.collect().foreach(println)

Itu bukanlah ide yang baik, meskipun, RDD memiliki milyaran baris. Gunakan take()untuk mengambil sedikit saja untuk dicetak:

myRDD.take(n).foreach(println)

1
jika saya menggunakan foreach di RDD (yang memiliki jutaan baris) untuk menulis konten ke dalam HDFS sebagai file tunggal, akankah berfungsi tanpa masalah pada cluster?
Shankar

Alasan saya tidak menggunakan saveAsTextFileRDD adalah, saya perlu menulis konten RDD menjadi lebih dari satu file, itulah mengapa saya menggunakanforeach
Shankar

Jika Anda ingin menyimpan dalam satu file, Anda dapat menggabungkan RDD Anda ke dalam satu partisi sebelum memanggil saveAsTextFile, tetapi sekali lagi ini dapat menyebabkan masalah. Saya pikir opsi terbaik adalah menulis dalam beberapa file dalam HDFS, lalu gunakan hdfs dfs --getmerge untuk menggabungkan file
Oussama

Anda mengatakan bahwa ketika menggunakan foreach pada RDD, ia akan menyimpannya di RAM driver, apakah Pernyataan tersebut benar? karena yang saya pahami adalah foreach akan berjalan pada setiap pekerja [cluster] bukan pada driver.
Shankar

saveAsTextFile akan menulis satu file per partisi, yang Anda inginkan (banyak file). Jika tidak, seperti yang disarankan Oussama, Anda bisa melakukan rdd.coalesce (1) .saveAsTextFile () untuk mendapatkan satu file. Jika RDD memiliki terlalu sedikit partisi yang Anda sukai, Anda dapat mencoba rdd.repartition (N) .saveAsTextFile ()
foghorn

49

The mapfungsi adalah transformasi , yang berarti bahwa Spark tidak akan benar-benar mengevaluasi RDD Anda sampai Anda menjalankan aksi di atasnya.

Untuk mencetaknya, Anda dapat menggunakan foreach(yang merupakan tindakan):

linesWithSessionId.foreach(println)

Untuk menulisnya ke disk, Anda dapat menggunakan salah satu saveAs...fungsi (tindakan diam) dari RDD API


6
Mungkin perlu Anda sebutkan collectagar RDD bisa dicetak di konsol.
zsxwing

1
foreachsendiri pertama-tama akan "mewujudkan" RDD dan kemudian menjalankan printlnsetiap elemen, jadi collecttidak terlalu dibutuhkan di sini (meskipun Anda dapat menggunakannya, tentu saja) ...
fedragon

5
Sebenarnya tanpa collect (), sebelum foreach, saya tidak dapat melihat apa pun di konsol.
Vittorio Cozzolino

3
Sebenarnya ini berfungsi dengan sangat baik di shell Spark saya, bahkan di 1.2.0. Tapi saya rasa saya tahu dari mana kebingungan ini berasal: pertanyaan asli menanyakan bagaimana cara mencetak RDD ke konsol Spark (= shell) jadi saya berasumsi dia akan menjalankan pekerjaan lokal, dalam hal ini foreachberfungsi dengan baik. Jika Anda menjalankan pekerjaan pada sebuah cluster dan Anda ingin mencetak rdd Anda maka Anda harus collect(seperti yang ditunjukkan oleh komentar dan jawaban lain) sehingga dikirim ke driver sebelum printlndijalankan. Dan menggunakan takeseperti yang disarankan oleh Oussama mungkin merupakan ide yang bagus jika RDD Anda terlalu besar.
fedragon

6
Jawaban di atas buruk. Anda harus tidak menerimanya. Foreach tidak akan mencetak ke konsol, itu akan mencetak pada node pekerja Anda. Jika Anda hanya memiliki satu node maka foreach akan bekerja. Tetapi jika Anda hanya memiliki satu node, lalu mengapa Anda menggunakan percikan? Cukup gunakan SQL awk, atau Grep, atau sesuatu yang lebih sederhana. Jadi saya pikir satu-satunya jawaban yang valid adalah mengumpulkan. Jika kumpulkan terlalu besar untuk Anda dan Anda hanya ingin mengambil sampel atau fungsi kepala atau serupa seperti yang dijelaskan di bawah ini.
eshalev

12

Jika Anda menjalankan ini di cluster maka printlntidak akan mencetak kembali ke konteks Anda. Anda perlu membawa RDDdata ke sesi Anda. Untuk melakukan ini, Anda dapat memaksanya ke array lokal dan kemudian mencetaknya:

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

12

Anda dapat mengubah Anda RDDmenjadi DataFramelalu show()itu.

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

Ini akan menampilkan 20 baris teratas dari data Anda, jadi ukuran data Anda seharusnya tidak menjadi masalah.

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

1
Saya pikir ituimport spark.implicits._
Ryan Hartman

Perpustakaan apa yang digunakan di sini? Saya tidak dapat mendeteksi toDFatau spark.implicits._dalam lingkup percikan.
Sergii

1

Mungkin ada banyak perbedaan arsitektural antara myRDD.foreach(println)dan myRDD.collect().foreach(println)(tidak hanya 'kumpulkan', tetapi juga tindakan lainnya). Salah satu perbedaan yang saya lihat adalah ketika melakukan myRDD.foreach(println), outputnya akan dalam urutan acak. Misalnya: jika rdd saya berasal dari file teks di mana setiap baris memiliki nomor, output akan memiliki urutan yang berbeda. Tetapi ketika saya melakukannya myRDD.collect().foreach(println), urutan tetap seperti file teks.


1

Dengan python

   linesWithSessionIdCollect = linesWithSessionId.collect()
   linesWithSessionIdCollect

Ini akan mencetak semua konten RDD


1
Terima kasih, tetapi saya menandai pertanyaan ini dengan scala bukan python
langit biru

1
c.take(10)

dan Spark versi yang lebih baru akan menampilkan tabel dengan baik.


1

Alih-alih mengetik setiap kali, Anda bisa;

[1] Buat metode cetak umum di dalam Spark Shell.

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

[2] Atau bahkan lebih baik, menggunakan implikasinya, Anda dapat menambahkan fungsi ke kelas RDD untuk mencetak isinya.

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

Contoh penggunaan:

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

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

Keluaran:

2
6
4
8

Penting

Ini hanya masuk akal jika Anda bekerja dalam mode lokal dan dengan sedikit kumpulan data. Jika tidak, Anda tidak akan dapat melihat hasilnya di klien atau kehabisan memori karena hasil dataset yang besar.



Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.