Làm thế nào để kiểm tra xem khung dữ liệu tia lửa có trống không?


101

Ngay bây giờ, tôi phải sử dụng df.count > 0để kiểm tra xem DataFramecó trống hay không. Nhưng nó là loại không hiệu quả. Có cách nào tốt hơn để làm điều đó không?

Cảm ơn.

Tái bút: Tôi muốn kiểm tra xem nó có trống không để tôi chỉ lưu DataFramenếu nó không trống

Câu trả lời:


154

Đối với Spark 2.1.0, đề xuất của tôi sẽ là sử dụng head(n: Int)hoặc take(n: Int)với isEmpty, bất kỳ cái nào có ý định rõ ràng nhất với bạn.

df.head(1).isEmpty
df.take(1).isEmpty

với Python tương đương:

len(df.head(1)) == 0  # or bool(df.head(1))
len(df.take(1)) == 0  # or bool(df.take(1))

Sử dụng df.first()df.head()cả hai sẽ trả về java.util.NoSuchElementExceptionnếu DataFrame trống. first()cuộc gọi head()trực tiếp, cuộc gọi nào head(1).head.

def first(): T = head()
def head(): T = head(1).head

head(1)trả về một Mảng, vì vậy việc sử dụng headMảng đó sẽ gây ra java.util.NoSuchElementExceptionkhi DataFrame trống.

def head(n: Int): Array[T] = withAction("head", limit(n).queryExecution)(collectFromPlan)

Vì vậy, thay vì gọi head(), hãy sử dụng head(1)trực tiếp để lấy mảng và sau đó bạn có thể sử dụng isEmpty.

take(n)cũng tương đương với head(n)...

def take(n: Int): Array[T] = head(n)

limit(1).collect()tương đương với head(1)(thông báo limit(n).queryExecutiontrong head(n: Int)phương thức), vì vậy tất cả những điều sau đây đều tương đương, ít nhất là từ những gì tôi có thể nói và bạn sẽ không phải bắt một java.util.NoSuchElementExceptionngoại lệ khi DataFrame trống.

df.head(1).isEmpty
df.take(1).isEmpty
df.limit(1).collect().isEmpty

Tôi biết đây là một câu hỏi cũ hơn nên hy vọng nó sẽ giúp ích cho ai đó đang sử dụng phiên bản Spark mới hơn.


19
Đối với những người sử dụng pyspark. isEmpty không phải là một thứ. Thay vào đó, hãy thực hiện len (d.head (1))> 0.
AntiPawn79,

3
tại sao điều này tốt hơn sau đó df.rdd.isEmpty?
Dan Ciborowski - MSFT

1
df.head (1) .isEmpty đang mất rất nhiều thời gian. Liệu có giải pháp tối ưu hóa nào khác cho việc này không.
Rakesh Sabbani

1
Xin chào @Rakesh Sabbani, Nếu df.head(1)mất nhiều thời gian, có thể là do dfkế hoạch thực hiện của bạn đang thực hiện điều gì đó phức tạp khiến tia lửa không thể thực hiện các phím tắt. Ví dụ: nếu bạn chỉ đọc từ các tệp parquet df = spark.read.parquet(...), tôi khá chắc chắn rằng spark sẽ chỉ đọc một phân vùng tệp. Nhưng nếu bạn dfđang làm những việc khác như tổng hợp, bạn có thể vô tình buộc spark đọc và xử lý một phần lớn dữ liệu nguồn của bạn, nếu không phải là tất cả.
hulin003

chỉ báo cáo trải nghiệm của tôi cho TRÁNH: Tôi đã sử dụng một cách df.limit(1).count()ngây thơ. Trên tập hợp dữ liệu lớn phải mất thời gian nhiều hơn so với các ví dụ báo cáo của @ hulin003 mà gần như tức thời
Vzzarr

45

Tôi sẽ nói chỉ lấy phần bên dưới RDD. Trong Scala:

df.rdd.isEmpty

bằng Python:

df.rdd.isEmpty()

Điều này đang được nói, tất cả những điều này là cuộc gọi take(1).length, vì vậy nó sẽ làm điều tương tự như Rohan đã trả lời ... chỉ có thể rõ ràng hơn một chút?


6
Điều này chậm hơn đáng ngạc nhiên so với df.count () == 0 trong trường hợp của tôi
kiến trúc sư

2
Không phải chuyển đổi sang rdd là một nhiệm vụ nặng nề?
Alok

1
Không hẳn vậy. RDD vẫn là nền tảng của mọi thứ Spark phần lớn.
Justin Pihony

28
Không chuyển đổi df thành RDD. Nó làm chậm quá trình. Nếu bạn chuyển đổi nó sẽ chuyển đổi toàn bộ DF sang RDD và kiểm tra xem nó có trống không. Hãy nghĩ nếu DF có hàng triệu hàng, thì sẽ mất rất nhiều thời gian để chuyển đổi sang RDD.
Nandakishore

3
.rdd làm chậm quá trình rất nhiều
Raul H

14

Bạn có thể tận dụng head()(hoặc first()) các hàm để xem liệu hàm DataFramecó một hàng hay không. Nếu vậy, nó không rỗng.


10
nếu dataframe trống, nó ném "java.util.NoSuchElementException: next on rỗng vòng lặp"; [Spark 1.3.1]
FelixHo

6

Kể từ khi có Spark 2.4.0 Dataset.isEmpty.

thực hiện là:

def isEmpty: Boolean = 
  withAction("isEmpty", limit(1).groupBy().count().queryExecution) { plan =>
    plan.executeCollect().head.getLong(0) == 0
}

Lưu ý rằng a DataFramekhông còn là một lớp trong Scala, nó chỉ là một bí danh kiểu (có thể được thay đổi với Spark 2.0):

type DataFrame = Dataset[Row]

1
isEmpty chậm hơn df.head (1) .isEmpty
Sandeep540

@ Sandeep540 Thật không? Điểm chuẩn? Đề xuất của bạn khởi tạo ít nhất một hàng. Việc triển khai Spark chỉ vận chuyển một số. head () cũng đang sử dụng limit (), groupBy () không thực sự làm bất cứ điều gì, nó được yêu cầu phải lấy RelationalGroupedDataset để cung cấp count (). Vì vậy, điều đó không nên chậm hơn đáng kể. Nó có thể nhanh hơn trong trường hợp tập dữ liệu chứa nhiều cột (có thể là dữ liệu lồng nhau không chuẩn hóa). Anway bạn phải gõ ít :-)
Berili

5

Đối với người dùng Java, bạn có thể sử dụng điều này trên tập dữ liệu:

public boolean isDatasetEmpty(Dataset<Row> ds) {
        boolean isEmpty;
        try {
            isEmpty = ((Row[]) ds.head(1)).length == 0;
        } catch (Exception e) {
            return true;
        }
        return isEmpty;
}

Điều này kiểm tra tất cả các trường hợp có thể xảy ra (trống, rỗng).


5

Nếu bạn làm df.count > 0. Nó lấy số lượng của tất cả các phân vùng trên tất cả các trình thực thi và thêm chúng vào Driver. Quá trình này mất một lúc khi bạn xử lý hàng triệu hàng.

Cách tốt nhất để làm điều này là thực hiện df.take(1)và kiểm tra xem nó có null hay không. Điều này sẽ trở lại java.util.NoSuchElementExceptiontốt hơn để thử xung quanh df.take(1).

Khung dữ liệu trả về lỗi khi take(1)hoàn tất thay vì một hàng trống. Tôi đã đánh dấu các dòng mã cụ thể mà nó gây ra lỗi.

nhập mô tả hình ảnh ở đây


1
nếu bạn chạy điều này trên một khung dữ liệu lớn với hàng triệu bản ghi thì countphương pháp này sẽ mất một khoảng thời gian.
TheM00s3

2
Tôi cũng nói như vậy, tôi không rõ tại sao bạn lại không thích.
Nandakishore

quyền của bạn, bạn đã nói như vậy, rất tiếc, tôi đã không tán thành bạn.
TheM00s3

Ồ, không sao. Tôi xin lỗi TheMoos3, nhưng ai đã làm điều đó, xin vui lòng quan sát câu trả lời và hiểu khái niệm.
Nandakishore

sử dụng df.take (1) khi df là kết quả có sản phẩm nào trong việc trở lại một ROW trống mà không thể so sánh với null
LetsPlayYahtzee

3

Trong Scala, bạn có thể sử dụng hàm ẩn để thêm các phương thức isEmpty()nonEmpty()API DataFrame, điều này sẽ làm cho mã dễ đọc hơn một chút.

object DataFrameExtensions {
  implicit def extendedDataFrame(dataFrame: DataFrame): ExtendedDataFrame = 
    new ExtendedDataFrame(dataFrame: DataFrame)

  class ExtendedDataFrame(dataFrame: DataFrame) {
    def isEmpty(): Boolean = dataFrame.head(1).isEmpty // Any implementation can be used
    def nonEmpty(): Boolean = !isEmpty
  }
}

Tại đây, các phương pháp khác cũng có thể được thêm vào. Để sử dụng chuyển đổi ngầm, hãy sử dụng import DataFrameExtensions._trong tệp bạn muốn sử dụng chức năng mở rộng. Sau đó, các phương pháp có thể được sử dụng trực tiếp như vậy:

val df: DataFrame = ...
if (df.isEmpty) {
  // Do something
}

2

Tôi có cùng một câu hỏi và tôi đã thử nghiệm 3 giải pháp chính:

  1. df! = null df.count> 0
  2. df.head (1) .isEmpty () as @ hulin003 suggest
  3. df.rdd.isEmpty như @Justin Pihony gợi ý

và tất nhiên cả 3 đều hoạt động, tuy nhiên về mặt hoàn hảo, đây là những gì tôi tìm thấy, khi thực hiện các phương thức này trên cùng một DF trong máy của tôi, trong thời gian thực thi:

  1. mất ~ 9366ms
  2. mất ~ 5607ms
  3. mất ~ 1921ms

do đó, tôi nghĩ rằng giải pháp tốt nhất là df.rdd.isEmpty như @Justin Pihony đề xuất


1
tùy chọn 3 mất ít thời gian hơn, tại sao lại là tùy chọn thứ hai?
thinkman

Rất tiếc, quyền của bạn, tôi đang sử dụng thứ 3, tôi cập nhật phản hồi
aName

vì tò mò ... DataFrames này đã được thử nghiệm với kích thước nào?
aiguofer

1

Tôi thấy rằng trong một số trường hợp:

>>>print(type(df))
<class 'pyspark.sql.dataframe.DataFrame'>

>>>df.take(1).isEmpty
'list' object has no attribute 'isEmpty'

điều này tương tự với "length" hoặc thay thế take () bằng head ()

[Giải pháp] cho vấn đề chúng tôi có thể sử dụng.

>>>df.limit(2).count() > 1
False

1

Nếu bạn đang sử dụng Pypsark, bạn cũng có thể làm:

len(df.head(1)) > 0

1

Trên PySpark, bạn cũng có thể sử dụng điều này bool(df.head(1))để có được một Truesố Falsegiá trị

Nó trả về Falsenếu khung dữ liệu không chứa hàng


0
df1.take(1).length>0

Các takephương thức trả về mảng hàng, vì vậy nếu kích thước mảng là bằng không, không có hồ sơ trong df.


-1

dataframe.limit(1).count > 0

Điều này cũng kích hoạt một công việc nhưng vì chúng tôi đang chọn bản ghi duy nhất, ngay cả trong trường hợp hàng tỷ bản ghi quy mô, mức tiêu thụ thời gian có thể thấp hơn nhiều.

Từ: https://medium.com/checking-emptiness-in-distributed-objects/count-vs-isempty-surprised-to-see-the-impact-fa70c0246ee0


Tất cả những lựa chọn này đều là những lựa chọn tồi mất thời gian gần như ngang nhau
Pushpendra Jaiswal

@PushpendraJaiswal vâng, và trong một thế giới của các lựa chọn tồi, chúng ta nên chọn phương án xấu tốt nhất
Jordan Morris

-2

Bạn có thể làm như sau:

val df = sqlContext.emptyDataFrame
if( df.eq(sqlContext.emptyDataFrame) )
    println("empty df ")
else 
    println("normal df")

1
nó sẽ không yêu cầu schemahai khung dữ liệu ( sqlContext.emptyDataFrame& df) giống nhau để bao giờ trả về true?
y2k-shubham

1
Điều này sẽ không hoạt động. eqđược kế thừa từ AnyRefkiểm tra xem đối số (cái đó) có phải là tham chiếu đến đối tượng người nhận (cái này) hay không.
Alper t. Turker
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.