Trích xuất giá trị cột của Dataframe dưới dạng Danh sách trong Apache Spark


86

Tôi muốn chuyển đổi một cột chuỗi của khung dữ liệu thành một danh sách. Những gì tôi có thể tìm thấy từ DataframeAPI là RDD, vì vậy tôi đã thử chuyển đổi nó trở lại RDD trước, và sau đó áp dụng toArraychức năng cho RDD. Trong trường hợp này, độ dài và SQL hoạt động tốt. Tuy nhiên, kết quả tôi nhận được từ RDD có dấu ngoặc vuông xung quanh mọi phần tử như thế này [A00001]. Tôi đã tự hỏi liệu có cách thích hợp để chuyển đổi một cột thành một danh sách hoặc một cách để loại bỏ các dấu ngoặc vuông.

Mọi lơi đê nghị đêu nên được đanh gia cao. Cảm ơn bạn!


Câu trả lời:


117

Thao tác này sẽ trả về bộ sưu tập có chứa một danh sách:

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()

Nếu không có ánh xạ, bạn chỉ nhận được một đối tượng Row, chứa mọi cột từ cơ sở dữ liệu.

Hãy nhớ rằng điều này có thể sẽ giúp bạn có danh sách Loại bất kỳ. ÏNếu bạn muốn chỉ định loại kết quả, bạn có thể sử dụng .asInstanceOf [YOUR_TYPE] trong r => r(0).asInstanceOf[YOUR_TYPE]ánh xạ

PS do chuyển đổi tự động bạn có thể bỏ qua .rddphần này.


3
Vì một số lý do kỳ lạ, nó hoạt động theo cách khác (Spark 2.1.0) collect().map(r => r(0))- thứ tự này có bất kỳ nhược điểm nào không?
Boern

Có thể chậm hơn - giải pháp của bạn trước tiên thu thập tất cả dữ liệu trên trình điều khiển và sau đó nó thực hiện ánh xạ trên trình điều khiển (không có sự trợ giúp của người thực thi), chỉ sử dụng sức mạnh xử lý của một trình điều khiển.
TheMP

72

Với Spark 2.x và Scala 2.11

Tôi nghĩ đến 3 cách khả thi để chuyển đổi giá trị của một cột cụ thể thành Danh sách.

Các đoạn mã chung cho tất cả các phương pháp

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.getOrCreate    
import spark.implicits._ // for .toDF() method

val df = Seq(
    ("first", 2.0),
    ("test", 1.5), 
    ("choose", 8.0)
  ).toDF("id", "val")

Phương pháp 1

df.select("id").collect().map(_(0)).toList
// res9: List[Any] = List(one, two, three)

Điều gì xảy ra bây giờ? Chúng tôi đang thu thập dữ liệu cho Trình điều khiển collect()và chọn phần tử 0 từ mỗi bản ghi.

Đây không thể là một cách làm xuất sắc, Hãy cải thiện nó bằng cách tiếp cận.


Cách tiếp cận 2

df.select("id").rdd.map(r => r(0)).collect.toList 
//res10: List[Any] = List(one, two, three)

Làm thế nào là nó tốt hơn? Chúng tôi đã phân phối tải chuyển đổi bản đồ giữa các công nhân thay vì một Trình điều khiển đơn lẻ.

Tôi biết rdd.map(r => r(0))không có vẻ thanh lịch bạn. Vì vậy, hãy giải quyết nó trong cách tiếp cận tiếp theo.


Phương pháp 3

df.select("id").map(r => r.getString(0)).collect.toList 
//res11: List[String] = List(one, two, three)

Ở đây chúng tôi không chuyển đổi DataFrame thành RDD. Hãy xem mapnó sẽ không chấp nhận r => r(0)(hoặc _(0)) như cách tiếp cận trước đây do sự cố bộ mã hóa trong DataFrame. Vì vậy, hãy kết thúc sử dụng r => r.getString(0)và nó sẽ được giải quyết trong các phiên bản tiếp theo của Spark.

Phần kết luận

Tất cả các tùy chọn đều cho kết quả như nhau nhưng 2 và 3 là hiệu quả, cuối cùng thì lựa chọn thứ 3 là hiệu quả và thanh lịch (tôi nghĩ vậy).

Sổ ghi chép Databricks


24

Tôi biết câu trả lời đưa ra và yêu cầu được giả định cho Scala, vì vậy tôi chỉ cung cấp một đoạn mã Python nhỏ trong trường hợp người dùng PySpark tò mò. Cú pháp tương tự như câu trả lời đã cho, nhưng để bật danh sách ra một cách chính xác, tôi thực sự phải tham chiếu tên cột lần thứ hai trong hàm ánh xạ và tôi không cần câu lệnh select.

tức là một DataFrame, chứa một cột có tên là "Raw"

Để nhận từng giá trị hàng trong "Raw" được kết hợp thành danh sách trong đó mỗi mục nhập là một giá trị hàng từ "Raw", tôi chỉ cần sử dụng:

MyDataFrame.rdd.map(lambda x: x.Raw).collect()

4
Điều này cung cấp một danh sách các đối tượng Row. Điều gì xảy ra nếu bạn muốn một danh sách các giá trị?
ThatDataGuy

Điều này cung cấp một danh sách các giá trị.
abby sobh

Cảm ơn vì đã chia sẻ điều này! Điều này rất hiệu quả đối với tôi, chỉ tự hỏi liệu có cách nào để tăng tốc độ này không, nó chạy khá chậm
Mojgan Mazouchi

5

Trong Scala và Spark 2+, hãy thử điều này (giả sử tên cột của bạn là "s"): df.select('s).as[String].collect


3
sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets

nó hoạt động hoàn hảo


1
List<String> whatever_list = df.toJavaRDD().map(new Function<Row, String>() {
    public String call(Row row) {
        return row.getAs("column_name").toString();
    }
}).collect();

logger.info(String.format("list is %s",whatever_list)); //verification

Vì không ai đưa ra giải pháp nào trong java (Ngôn ngữ lập trình thực) Có thể cảm ơn tôi sau


0
from pyspark.sql.functions import col

df.select(col("column_name")).collect()

ở đây thu thập là các chức năng lần lượt chuyển đổi nó thành danh sách. Hãy sử dụng danh sách trên tập dữ liệu khổng lồ. Nó sẽ làm giảm hiệu suất. Nó là tốt để kiểm tra dữ liệu.


0

Đây là câu trả lời java.

df.select("id").collectAsList();

0

Một giải pháp cập nhật giúp bạn có một danh sách:

dataFrame.select("YOUR_COLUMN_NAME").map(r => r.getString(0)).collect.toList
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.