Câu trả lời:
Đố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()
và df.head()
cả hai sẽ trả về java.util.NoSuchElementException
nế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 head
Mảng đó sẽ gây ra java.util.NoSuchElementException
khi 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)
Và limit(1).collect()
tương đương với head(1)
(thông báo limit(n).queryExecution
trong 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.NoSuchElementException
ngoạ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.
df.rdd.isEmpty
?
df.head(1)
mất nhiều thời gian, có thể là do df
kế 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ả.
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
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?
Bạn có thể tận dụng head()
(hoặc first()
) các hàm để xem liệu hàm DataFrame
có một hàng hay không. Nếu vậy, nó không rỗng.
Kể từ khi có Spark 2.4.0 Dataset.isEmpty
.
Nó 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 DataFrame
khô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]
Đố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).
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.NoSuchElementException
tố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.
count
phương pháp này sẽ mất một khoảng thời gian.
Trong Scala, bạn có thể sử dụng hàm ẩn để thêm các phương thức isEmpty()
và 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
}
Tôi có cùng một câu hỏi và tôi đã thử nghiệm 3 giải pháp chính:
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:
do đó, tôi nghĩ rằng giải pháp tốt nhất là df.rdd.isEmpty như @Justin Pihony đề xuất
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
Nếu bạn đang sử dụng Pypsark, bạn cũng có thể làm:
len(df.head(1)) > 0
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.
Bạn có thể làm như sau:
val df = sqlContext.emptyDataFrame
if( df.eq(sqlContext.emptyDataFrame) )
println("empty df ")
else
println("normal df")
schema
hai khung dữ liệu ( sqlContext.emptyDataFrame
& df
) giống nhau để bao giờ trả về true
?
eq
được kế thừa từ AnyRef
và kiể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.