Làm thế nào để in nội dung của RDD?


124

Tôi đang cố in nội dung của bộ sưu tập lên bảng điều khiển Spark.

Tôi có một loại:

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

Và tôi sử dụng lệnh:

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

Nhưng điều này được in:

res1: org.apache.spark.rdd.RDD [Đơn vị] = MappedRDD [4] tại bản đồ tại: 19

Làm cách nào tôi có thể ghi RDD vào bàn điều khiển hoặc lưu nó vào đĩa để tôi có thể xem nội dung của nó?


1
Chào! bạn đã đọc những bình luận về câu trả lời, được bạn chấp nhận chưa? Nó dường như gây hiểu lầm
dk14

2
@ dk14 đồng ý, tôi đã chỉ định lại câu trả lời được chấp nhận
bầu trời xanh

RDD đang xuống hạng với tư cách là công dân hạng hai, bạn nên sử dụng DataFrame và showphương thức.
Thomas Decaux

Câu trả lời:


235

Nếu bạn muốn xem nội dung của RDD, một cách là sử dụng collect():

myRDD.collect().foreach(println)

Tuy nhiên, đó không phải là một ý tưởng hay khi RDD có hàng tỷ dòng. Sử dụng take()để chỉ mất một vài để in ra:

myRDD.take(n).foreach(println)

1
Nếu tôi sử dụng foreach trên RDD (có hàng triệu dòng) để ghi nội dung vào HDFS dưới dạng một tệp, nó có hoạt động mà không có bất kỳ vấn đề nào trên cụm không?
Shankar

Lý do tôi không sử dụng saveAsTextFiletrên RDD là vì tôi cần phải viết nội dung RDD vào nhiều tệp, đó là lý do tại sao tôi đang sử dụngforeach
Shankar

Nếu bạn muốn lưu trong một tệp duy nhất, bạn có thể kết hợp RDD của bạn vào một phân vùng trước khi gọi saveAsTextFile, nhưng một lần nữa điều này có thể gây ra sự cố. Tôi nghĩ tùy chọn tốt nhất là ghi vào nhiều tệp trong HDFS, sau đó sử dụng hdfs dfs --getmerge để hợp nhất các tệp
Oussama

bạn đã nói rằng khi sử dụng foreach trên RDD, nó sẽ lưu nó vào RAM của trình điều khiển, Tuyên bố có đúng không? bởi vì những gì tôi hiểu là foreach sẽ chạy trên mỗi worker [cluster] chứ không phải trên driver.
Shankar

saveAsTextFile sẽ ghi một tệp trên mỗi phân vùng, đó là những gì bạn muốn (nhiều tệp). Mặt khác, như Oussama gợi ý, bạn có thể thực hiện rdd.coalesce (1) .saveAsTextFile () để lấy một tệp. Nếu RDD có quá ít phân vùng theo ý thích của bạn, bạn có thể thử rdd.repartition (N) .saveAsTextFile ()
tiếng như bò rống

49

Các mapchức năng là một chuyển đổi , có nghĩa là Spark sẽ không thực sự đánh giá RDD của bạn cho đến khi bạn chạy một hành động trên nó.

Để in nó, bạn có thể sử dụng foreach(đó là một hành động):

linesWithSessionId.foreach(println)

Để ghi nó vào đĩa, bạn có thể sử dụng một trong các saveAs...hàm (hành động tĩnh) từ API RDD


6
Có lẽ bạn cần đề cập collectđể RDD có thể được in trong bảng điều khiển.
zsxwing

1
foreachbản thân nó trước tiên sẽ "cụ thể hóa" RDD và sau đó chạy printlntrên từng phần tử, vì vậy collectkhông thực sự cần thiết ở đây (mặc dù bạn có thể sử dụng nó, tất nhiên) ...
fedragon

5
Trên thực tế mà không thu thập (), trước khi tìm kiếm, tôi không thể thấy bất cứ điều gì trên bảng điều khiển.
Vittorio Cozzolino

3
Trên thực tế, nó hoạt động hoàn toàn tốt trong vỏ Spark của tôi, ngay cả trong 1.2.0. Nhưng tôi nghĩ tôi biết sự nhầm lẫn này đến từ đâu: câu hỏi ban đầu hỏi cách in RDD sang bảng điều khiển Spark (= shell) vì vậy tôi cho rằng anh ta sẽ điều hành một công việc cục bộ, trong trường hợp này foreachhoạt động tốt. Nếu bạn đang chạy một công việc trên một cụm và bạn muốn in rdd của mình thì bạn nên collect(như được chỉ ra bởi các nhận xét và câu trả lời khác) để nó được gửi đến trình điều khiển trước khi printlnđược thực thi. Và sử dụng taketheo đề xuất của Oussama có thể là một ý tưởng tốt nếu RDD của bạn quá lớn.
fedragon 7/1/2015

6
Câu trả lời trên là xấu. Bạn không nên chấp nhận nó. Foreach sẽ không in ra bàn điều khiển, nó sẽ in trên các nút worker của bạn. Nếu bạn chỉ có một nút thì foreach sẽ hoạt động. Nhưng nếu bạn chỉ có một nút, thì tại sao bạn lại sử dụng tia lửa? Chỉ cần sử dụng SQL awk hoặc Grep hoặc một cái gì đó đơn giản hơn nhiều. Vì vậy, tôi nghĩ rằng câu trả lời hợp lệ duy nhất là thu thập. Nếu việc thu thập là lớn đối với bạn và bạn chỉ muốn sử dụng một chức năng lấy hoặc đầu hoặc simillar như mô tả dưới đây.
eshalev

12

Nếu bạn đang chạy cái này trên một cụm thì printlnsẽ không in lại ngữ cảnh của bạn. Bạn cần mang RDDdữ liệu đến phiên của bạn. Để làm điều này, bạn có thể buộc nó vào mảng cục bộ và sau đó in nó ra:

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

12

Bạn có thể chuyển đổi của bạn RDDđể DataFramesau đó show()nó.

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

Điều này sẽ hiển thị 20 dòng dữ liệu hàng đầu của bạn, vì vậy kích thước của dữ liệu của bạn không phải là một vấn đề.

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

1
Tôi nghĩ đó làimport spark.implicits._
Ryan Hartman

Thư viện đã được sử dụng ở đây là gì? Tôi không thể phát hiện toDFhoặc spark.implicits._trong phạm vi tia lửa.
Sergii

1

Có lẽ có nhiều sự khác biệt về kiến ​​trúc giữa myRDD.foreach(println)myRDD.collect().foreach(println)(không chỉ 'thu thập', mà còn các hành động khác). Một trong những khác biệt tôi thấy là khi thực hiện myRDD.foreach(println), đầu ra sẽ theo thứ tự ngẫu nhiên. Ví dụ: nếu rdd của tôi đến từ tệp văn bản trong đó mỗi dòng có một số, đầu ra sẽ có một thứ tự khác nhau. Nhưng khi tôi đã làm myRDD.collect().foreach(println), thứ tự vẫn giống như các tập tin văn bản.


1

Trong trăn

   linesWithSessionIdCollect = linesWithSessionId.collect()
   linesWithSessionIdCollect

Điều này sẽ in ra tất cả các nội dung của RDD


1
Cảm ơn nhưng tôi đã gắn thẻ câu hỏi này với scala không phải python
blue-sky

1
c.take(10)

và Spark phiên bản mới hơn sẽ hiển thị bảng độc đáo.


1

Thay vì gõ mỗi lần, bạn có thể;

[1] Tạo phương thức in chung trong Spark Shell.

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

[2] Hoặc thậm chí tốt hơn, bằng cách sử dụng các ẩn ý, ​​bạn có thể thêm chức năng vào lớp RDD để in nội dung của nó.

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

Ví dụ sử dụng:

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

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

Đầu ra:

2
6
4
8

Quan trọng

Điều này chỉ có ý nghĩa nếu bạn đang làm việc ở chế độ cục bộ và với một lượng nhỏ dữ liệu được đặt. Mặt khác, bạn sẽ không thể xem kết quả trên máy khách hoặc hết bộ nhớ vì kết quả bộ dữ liệu lớn.


0

Bạn cũng có thể lưu dưới dạng tệp: rdd.saveAsTextFile("alicia.txt")


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.