Kıvılcım veri çerçevesinin boş olup olmadığı nasıl kontrol edilir?


105

Şu anda boş df.count > 0olup olmadığını kontrol etmek için kullanmalıyım DataFrame. Ama biraz verimsiz. Bunu yapmanın daha iyi bir yolu var mı?

Teşekkürler.

Not: Boş olup olmadığını kontrol etmek istiyorum, böylece yalnızca DataFrameboş değilse kaydediyorum

Yanıtlar:


158

Spark 2.1.0, benim önerim kullanımına olacağını head(n: Int)veya take(n: Int)birlikte isEmptybiri size niyet en net sahiptir hangisi.

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

Python eşdeğeri ile:

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

Kullanılması df.first()ve df.head()hem dönecektir java.util.NoSuchElementExceptionDataFrame boşsa. doğrudan first()arar head(), hangi arar head(1).head.

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

head(1)Bir Dizi döndürür, dolayısıyla bu Dizinin alınması DataFrame boş olduğunda headneden olur java.util.NoSuchElementException.

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

Bunun yerine çağırmak head(), kullanmak head(1)dizisini almak için doğrudan ve sonra kullanabilirsiniz isEmpty.

take(n)aynı zamanda eşdeğerdir head(n)...

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

Ve ( yöntemdeki uyarı ) limit(1).collect()ile eşdeğerdir , bu nedenle aşağıdakilerin tümü eşdeğerdir, en azından benim söyleyebileceğim kadarıyla ve DataFrame boşken bir istisna yakalamak zorunda kalmayacaksınız.head(1)limit(n).queryExecutionhead(n: Int)java.util.NoSuchElementException

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

Bunun daha eski bir soru olduğunu biliyorum, bu yüzden umarım Spark'ın daha yeni bir sürümünü kullanan birine yardımcı olur.


20
Pyspark kullananlar için. isEmpty bir şey değildir. Bunun yerine len (d.head (1))> 0 yapın.
AntiPawn79

5
o zaman bu neden daha iyi df.rdd.isEmpty?
Dan Ciborowski - MSFT

1
df.head (1) .isEmpty çok zaman alıyor, bunun için optimize edilmiş başka bir çözüm var mı?
Rakesh Sabbani

1
Hey @Rakesh Sabbani, df.head(1)Çok fazla zaman alıyorsanız, bunun nedeni muhtemelendf yürütme planınızın kıvılcımın kestirmeden kaçmasını engelleyen karmaşık bir şey yapmasıdır . Örneğin, sadece parke dosyalarından okuyorsanız, spark'ın df = spark.read.parquet(...)sadece bir dosya bölümünü okuyacağından oldukça eminim. Ancak df, toplama gibi başka şeyler yapıyorsanız, kıvılcımı, kaynak verilerinizin tümü olmasa da büyük bir bölümünü okumaya ve işlemeye istemeden zorlayabilirsiniz.
hulin003

deneyimimi sadece AVOID'e bildiriyorum: df.limit(1).count()Safça kullanıyordum . Büyük veri kümelerinde, @ hulin003 tarafından bildirilen ve neredeyse anlık olan örneklerden çok daha fazla zaman alıyor
Vzzarr

47

Ben sadece altta yatan şeyi kavramayı söyleyebilirim RDD. Scala'da:

df.rdd.isEmpty

Python'da:

df.rdd.isEmpty()

Olduğu söyleniyor, tüm bunlar çağrı take(1).length, yani Rohan'ın cevapladığı şeyi yapacak ... belki biraz daha açık?


6
Bu benim durumumda şaşırtıcı derecede df.count () == 0'dan daha yavaş
mimari

2
RDD'ye dönüştürmek ağır bir görev değil mi?
Alok

1
Pek sayılmaz. RDD'ler hala Spark'ın her şeyin temelini oluşturuyor.
Justin Pihony

28
Df'yi RDD'ye dönüştürmeyin. Süreci yavaşlatır. Dönüştürürseniz, tüm DF'yi RDD'ye dönüştürecek ve boş olup olmadığını kontrol edecektir. DF'nin milyonlarca satırı varsa, RDD'ye dönüştürmenin çok zaman aldığını düşünün.
Nandakishore

3
.rdd, süreci çok fazla yavaşlatıyor
Raul H

14

Tek bir satırın olup olmadığını görmek için head()(veya first()) işlevlerinden yararlanabilirsiniz DataFrame. Eğer öyleyse boş değildir.


10
veri çerçevesi boşsa, "java.util.NoSuchElementException: boş yineleyicide sonraki" değerini atar; [Spark 1.3.1]
FelixHo

8

Spark 2.4.0'dan beri var Dataset.isEmpty.

It adlı uygulama geçerli:

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

A'nın DataFrameartık Scala'da bir sınıf olmadığını, yalnızca bir tür takma adı olduğunu unutmayın (muhtemelen Spark 2.0 ile değiştirildi):

type DataFrame = Dataset[Row]

1
isEmpty, df.head (1) .isEmpty
Sandeep540

@ Sandeep540 Gerçekten mi? Kıyaslama mı? Teklifiniz en az bir satırı somutlaştırıyor. Spark uygulaması yalnızca bir sayıyı taşır. head () de limit () kullanıyor, groupBy () aslında hiçbir şey yapmıyor, bunun karşılığında count () sağlayan bir RelationalGroupedDataset almak gerekiyor. Bu, önemli ölçüde daha yavaş olmamalıdır. Çok sayıda sütun içeren (muhtemelen normal olmayan iç içe geçmiş veriler) bir veri kümesi durumunda muhtemelen daha hızlıdır. Daha az yazmak zorunda Anway :-)
Berilyum

7

Eğer yaparsan df.count > 0. Tüm yürütücülerdeki tüm bölümlerin sayılarını alır ve bunları Sürücü'de toplar. Milyonlarca satırla uğraşırken bu biraz zaman alır.

Bunu yapmanın en iyi yolu yapmak df.take(1)ve boş olup olmadığını kontrol etmektir . Bu, java.util.NoSuchElementExceptiondenemek için çok daha iyi dönecek df.take(1).

Veri çerçevesi take(1), bittiğinde boş bir satır yerine bir hata döndürür . Hatayı attığı belirli kod satırlarını vurguladım.

görüntü açıklamasını buraya girin


1
Bunu milyonlarca kayıt içeren devasa bir veri çerçevesinde çalıştırırsanız, bu countyöntem biraz zaman alacaktır.
TheM00s3

2
Ben de aynısını söyledim, neden başparmak aşağı verdiğinden emin değilim.
Nandakishore

Senin hakkın sen de aynısını söyledin, ne yazık ki, ben sana olumsuz oy vermedim.
TheM00s3

Ohhh tamam. Üzgünüm TheMoos3, ama bunu kim yaptıysa lütfen cevabı gözlemleyin ve kavramı anlayın.
Nandakishore

1
@LetsPlayYahtzee Cevabı aynı çalıştırma ve hata gösteren resimle güncelledim. take (1), Dizi [Satır] döndürür. Ve Array herhangi bir değere sahip olmadığında, varsayılan olarak ArrayOutOfBounds verir. Bu yüzden boş bir Satır verdiğini sanmıyorum. Bunu gözlemleyin ve oylamayı değiştirin derim.
Nandakishore

5

Java kullanıcıları için bunu bir veri kümesinde kullanabilirsiniz:

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

Bu, tüm olası senaryoları kontrol eder (boş, boş).


4

Scala'da yöntemleri ve DataFrame API'sine eklemek için implicits kullanabilirsiniz ; bu, kodu okumak için biraz daha hoş hale getirir.isEmpty()nonEmpty()

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

Burada başka yöntemler de eklenebilir. Örtük dönüştürmeyi import DataFrameExtensions._kullanmak için, genişletilmiş işlevselliği kullanmak istediğiniz dosyada kullanın. Daha sonra yöntemler doğrudan şu şekilde kullanılabilir:

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

3

Aynı soruyu sordum ve 3 ana çözümü test ettim:

  1. df! = boş df.count> 0
  2. df.head (1) .isEmpty () @ hulin003'ün önerdiği gibi
  3. df.rdd.isEmpty @ Justin Pihony'nin önerdiği gibi

ve tabii ki 3 çalışır, ancak performans açısından, işte bulduğum şey, bu yöntemleri kendi makinemdeki aynı DF üzerinde yürütme süresi içinde çalıştırırken:

  1. ~ 9366ms sürer
  2. ~ 5607ms sürer
  3. ~ 1921ms sürer

bu nedenle en iyi çözümün @Justin Pihony'nin önerdiği gibi df.rdd.isEmpty olduğunu düşünüyorum


1
3. seçenek daha az zaman alıyor, neden ikincisi?
thinkman

Ooops, haklısın, 3. kullanıyorum, yanıtı güncelliyorum
aName

1
meraktan ... bu hangi boyuttaki DataFrame'ler ile test edildi?
aiguofer

1

Bunu bazı durumlarda buldum:

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

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

bu "uzunluk" için aynıdır veya take () 'i başlık () ile değiştirin

Kullanabileceğimiz sorun için [Çözüm].

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

1

Pypsark kullanıyorsanız şunları da yapabilirsiniz:

len(df.head(1)) > 0

1

PySpark'ta, bunu bool(df.head(1))bir değer elde etmek için de kullanabilirsiniz True.False

FalseVeri çerçevesi satır içermiyorsa döndürür


0
df1.take(1).length>0

takeYöntem, bir dizi büyüklüğü sıfıra eşit olacak şekilde ise, satır dizi döndürür, hiçbir kayıt vardır df.


-1

dataframe.limit(1).count > 0

Bu aynı zamanda bir işi de tetikliyor, ancak tek bir kayıt seçtiğimiz için, milyar ölçekli kayıtlarda bile zaman tüketimi çok daha düşük olabilir.

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


Tüm bunlar neredeyse eşit zaman alan kötü seçenekler
Pushpendra Jaiswal

@PushpendraJaiswal evet ve kötü seçeneklerin olduğu bir dünyada, en kötü seçeneği seçmeliyiz
Jordan Morris

-2

Bunu şu şekilde yapabilirsiniz:

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

1
Geri dönmek için schemaiki veri çerçevesinin ( sqlContext.emptyDataFrame& df) aynı olmasını gerektirmez truemi?
y2k-shubham

1
Bu işe yaramayacak. eqmiras alınır AnyRefve bağımsız değişkenin (that) alıcı nesneye (this) bir başvuru olup olmadığını test eder.
Alper t. Türker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.