Bagaimana cara memeriksa apakah spark dataframe kosong?


102

Sekarang, saya harus menggunakan df.count > 0untuk memeriksa apakah DataFramekosong atau tidak. Tapi ini agak tidak efisien. Apakah ada cara yang lebih baik untuk melakukan itu?

Terima kasih.

PS: Saya mau cek kalau kosong jadi saya simpan saja DataFramekalau tidak kosong

Jawaban:


155

Untuk Spark 2.1.0, saran saya adalah menggunakan head(n: Int)atau take(n: Int)dengan isEmpty, mana saja yang memiliki maksud paling jelas untuk Anda.

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

dengan padanan Python:

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

Menggunakan df.first()dan df.head()akan mengembalikan java.util.NoSuchElementExceptionjika DataFrame kosong. first()panggilan head()langsung, yang memanggil head(1).head.

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

head(1)mengembalikan Array, jadi mengambil headArray itu menyebabkan java.util.NoSuchElementExceptionkapan DataFrame kosong.

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

Jadi, alih-alih memanggil head(), gunakan head(1)langsung untuk mendapatkan array lalu Anda bisa menggunakan isEmpty.

take(n)juga setara dengan head(n)...

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

Dan limit(1).collect()setara dengan head(1)(perhatikan limit(n).queryExecutiondalam head(n: Int)metode), jadi berikut ini semua setara, setidaknya dari apa yang saya tahu, dan Anda tidak perlu menangkap java.util.NoSuchElementExceptionpengecualian saat DataFrame kosong.

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

Saya tahu ini adalah pertanyaan lama, jadi semoga ini akan membantu seseorang yang menggunakan versi Spark yang lebih baru.


20
Bagi yang menggunakan pyspark. isEmpty bukanlah sesuatu. Lakukan len (d.head (1))> 0 sebagai gantinya.
AntiPawn79

5
mengapa ini lebih baik df.rdd.isEmpty?
Dan Ciborowski - MSFT

1
df.head (1) .isEmpty membutuhkan banyak waktu, apakah ada solusi lain yang dioptimalkan untuk ini.
Rakesh Sabbani

1
Hai @Rakesh Sabbani, Jika df.head(1)memakan banyak waktu, mungkin karena dfrencana eksekusi Anda melakukan sesuatu yang rumit yang mencegah percikan mengambil jalan pintas. Misalnya, jika Anda hanya membaca dari file parket df = spark.read.parquet(...), saya cukup yakin spark hanya akan membaca satu partisi file. Tetapi jika Anda dfmelakukan hal-hal lain seperti agregasi, Anda mungkin secara tidak sengaja memaksa percikan untuk membaca dan memproses sebagian besar, jika tidak semua, data sumber Anda.
hulin003

hanya melaporkan pengalaman saya ke HINDARI: Saya menggunakan secara df.limit(1).count()naif. Pada kumpulan data besar, dibutuhkan lebih banyak waktu daripada contoh yang dilaporkan oleh @ hulin003 yang hampir seketika
Vzzarr

45

Saya akan mengatakan untuk mengambil yang mendasarinya RDD. Di Scala:

df.rdd.isEmpty

dengan Python:

df.rdd.isEmpty()

Yang sedang berkata, semua ini adalah panggilan take(1).length, jadi itu akan melakukan hal yang sama seperti yang dijawab Rohan ... mungkin sedikit lebih eksplisit?


6
Ini ternyata lebih lambat daripada df.count () == 0 dalam kasus saya
arsitektonis

2
Bukankah mengonversi ke rdd merupakan tugas yang berat?
Alok

1
Tidak juga. RDD masih menjadi pendukung dari sebagian besar Spark.
Justin Pihony

28
Jangan ubah df ke RDD. Ini memperlambat proses. Jika Anda mengonversinya akan mengubah seluruh DF menjadi RDD dan memeriksa apakah itu kosong. Pikirkan jika DF memiliki jutaan baris, butuh banyak waktu untuk mengubahnya menjadi RDD itu sendiri.
Nandakishore

3
.rdd memperlambat begitu banyak proses seperti banyak
Raul H

14

Anda dapat memanfaatkan fungsi head()(atau first()) untuk melihat apakah DataFramememiliki satu baris. Jika demikian, itu tidak kosong.


10
jika dataframe kosong maka "java.util.NoSuchElementException: next on empty iterator"; [Spark 1.3.1]
FelixHo

6

Jika Anda melakukannya df.count > 0. Dibutuhkan jumlah semua partisi di semua pelaksana dan menambahkannya di Driver. Ini membutuhkan waktu lama ketika Anda berurusan dengan jutaan baris.

Cara terbaik untuk melakukannya adalah dengan melakukan df.take(1)dan memeriksa apakah nilainya null. Ini akan kembali java.util.NoSuchElementExceptionjadi lebih baik untuk mencobanya df.take(1).

Dataframe mengembalikan kesalahan saat take(1)selesai, bukan baris kosong. Saya telah menyoroti baris kode tertentu di mana ia melempar kesalahan.

masukkan deskripsi gambar di sini


1
jika Anda menjalankan ini pada kerangka data besar dengan jutaan catatan, countmetode itu akan memakan waktu.
TheM00s3

2
Saya mengatakan hal yang sama, saya tidak yakin mengapa Anda memberi jempol ke bawah.
Nandakishore

hak Anda, Anda mengatakan hal yang sama, sayangnya, saya tidak meremehkan Anda.
TheM00s3

Ohhh oke. Saya minta maaf TheMoos3, tetapi siapa pun yang melakukannya, harap perhatikan jawabannya dan pahami konsepnya.
Nandakishore

menggunakan df.take (1) ketika df kosong menghasilkan kembali ROW kosong yang tidak dapat dibandingkan dengan null
LetsPlayYahtzee

6

Sejak Spark 2.4.0 ada Dataset.isEmpty.

Itu implementasi adalah:

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

Perhatikan bahwa a DataFramebukan lagi kelas di Scala, itu hanya alias tipe (mungkin diubah dengan Spark 2.0):

type DataFrame = Dataset[Row]

1
isEmpty lebih lambat dari df.head (1) .isEmpty
Sandeep540

@ Sandeep540 Benarkah? Tolok ukur? Proposal Anda membuat contoh setidaknya satu baris. Implementasi Spark hanya mengirimkan nomor. head () menggunakan limit () juga, groupBy () tidak benar-benar melakukan apa pun, itu diperlukan untuk mendapatkan RelationalGroupedDataset yang pada gilirannya menyediakan count (). Sehingga seharusnya tidak lebih lambat secara signifikan. Ini mungkin lebih cepat dalam kasus kumpulan data yang berisi banyak kolom (mungkin mendenormalisasi data bersarang). Lagi pula Anda harus mengetik lebih sedikit :-)
Berilium

5

Untuk pengguna Java, Anda dapat menggunakan ini di set data:

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

Ini memeriksa semua kemungkinan skenario (kosong, null).


3

Di Scala, Anda dapat menggunakan implik untuk menambahkan metode isEmpty()dan nonEmpty()ke DataFrame API, yang akan membuat kode sedikit lebih bagus untuk dibaca.

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
  }
}

Di sini, metode lain juga dapat ditambahkan. Untuk menggunakan konversi implisit, gunakan import DataFrameExtensions._file yang ingin Anda gunakan dengan fungsionalitas yang diperluas. Setelah itu, metode dapat digunakan secara langsung sebagai berikut:

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

2

Saya memiliki pertanyaan yang sama, dan saya menguji 3 solusi utama:

  1. df! = null df.count> 0
  2. df.head (1) .isEmpty () seperti yang disarankan @ hulin003
  3. df.rdd.isEmpty sebagai saran @Justin Pihony

dan tentu saja 3 berfungsi, namun dalam hal kinerja, inilah yang saya temukan, ketika menjalankan metode ini pada DF yang sama di mesin saya, dalam hal waktu eksekusi:

  1. dibutuhkan ~ 9366ms
  2. dibutuhkan ~ 5607ms
  3. dibutuhkan ~ 1921ms

oleh karena itu saya pikir solusi terbaik adalah df.rdd.isEmpty seperti yang disarankan @Justin Pihony


1
opsi 3 membutuhkan lebih sedikit waktu, mengapa yang kedua?
pemikir

Ups, Anda benar, saya menggunakan yang ketiga, saya memperbarui tanggapan
aName

karena penasaran ... dengan ukuran apa DataFrames ini diuji?
aiguofer

1

Saya menemukan itu pada beberapa kasus:

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

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

ini sama untuk "length" atau ganti take () dengan head ()

[Solusi] untuk masalah yang bisa kita gunakan.

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

1

Jika Anda menggunakan Pypsark, Anda juga dapat melakukan:

len(df.head(1)) > 0

1

Pada PySpark, Anda juga dapat menggunakan ini bool(df.head(1))untuk mendapatkan Truedari Falsenilai

Ia kembali Falsejika dataframe tidak berisi baris


0
df1.take(1).length>0

The takeMetode mengembalikan array baris, jadi jika ukuran array sama dengan nol, tidak ada catatan di df.


-1

dataframe.limit(1).count > 0

Ini juga memicu pekerjaan tetapi karena kami memilih satu catatan, bahkan dalam kasus catatan skala miliar konsumsi waktu bisa jauh lebih rendah.

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


Semua ini adalah opsi buruk yang memakan waktu hampir sama
Pushpendra Jaiswal

@PushpendraJaiswal ya, dan di dunia dengan opsi yang buruk, kita harus memilih opsi terbaik yang buruk
Jordan Morris

-2

Anda bisa melakukannya seperti:

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

1
bukankah itu membutuhkan schemadua dataframe ( sqlContext.emptyDataFrame& df) untuk sama agar bisa kembali true?
y2k-shubham

1
Ini tidak akan berhasil. eqdiwarisi dari AnyRefdan menguji apakah argumen (itu) adalah referensi ke objek penerima (ini).
Alper t. Turker
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.