Sparkデータフレームが空かどうかを確認するにはどうすればよいですか?


100

現在、が空かdf.count > 0どうかを確認するために使用するDataFrame必要があります。しかし、それは一種の非効率的です。それを行うより良い方法はありますか?

ありがとう。

PS:空でないかどうかを確認して、DataFrame空でない場合にのみ保存した​​い

回答:


153

スパーク2.1.0のために、私の提案は、使用することですhead(n: Int)か、take(n: Int)isEmptyもあなたに明確な意図を持っている方、。

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

同等のPythonを使用:

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

とを使用するdf.first()と、DataFrameが空の場合にdf.head()両方が返されjava.util.NoSuchElementExceptionます。first()head()直接呼び出され、が呼び出されますhead(1).head

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

head(1)は配列を返すためhead、その配列をjava.util.NoSuchElementException取得すると、DataFrameが空のときにが発生します。

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

したがって、を呼び出す代わりにhead()head(1)直接使用して配列を取得すると、を使用できますisEmpty

take(n)head(n)... と同等です

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

そして、limit(1).collect()同等ですhead(1)(予告limit(n).queryExecutionではhead(n: Int)、以下が、少なくとも私が言うことができるものから、全て等価であり、あなたがキャッチする必要はありませんので、方法)java.util.NoSuchElementExceptionデータフレームが空の場合に例外を。

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

私はこれが古い質問であることを知っているので、うまくいけば、新しいバージョンのSparkを使用している人に役立つでしょう。


19
pysparkを使用しているユーザー向け。isEmptyは事ではありません。代わりにlen(d.head(1))> 0を実行してください。
AntiPawn79 2017年

3
なぜこれが良いのdf.rdd.isEmptyですか?
Dan Ciborowski-MSFT、2018年

1
df.head(1).isEmptyが非常に時間がかかっていますが、これのために他の最適化されたソリューションがあります。
Rakesh Sabbani

1
@Rakesh Sabbani様df.head(1)、時間がかかっている場合は、おそらくdfsの実行計画が、sparkがショートカットを取得できないような複雑な処理を行っていることが原因です。たとえば、単に寄木細工のファイルから読み取る場合df = spark.read.parquet(...)、sparkは1つのファイルパーティションのみを読み取ると確信しています。しかし、df集計などの他のことをしている場合は、誤って、sparkにソースデータのすべてではないにしても、大部分を読み取って処理させる可能性があります。
hulin003

私の経験をAVOIDに報告するだけdf.limit(1).count()です。大きなデータセットでは、ほぼ瞬時に報告される@ hulin003によって報告された例よりもはるかに時間がかかります
Vzzarr

45

根底にあるものをつかむだけRDDです。Scalaの場合:

df.rdd.isEmpty

Pythonの場合:

df.rdd.isEmpty()

そうは言っても、これはcall take(1).lengthだけなので、Rohanが答えたのと同じことをします...もう少し明示的でしょうか?


6
私の場合、これはdf.count()== 0よりも驚くほど遅い
アーキテクチャー

2
rddへの変換は大変な作業ではありませんか?
Alok、2016年

1
あんまり。RDDは依然としてほとんどすべてのSparkを支えています。
Justin Pihony 2016

28
dfをRDDに変換しないでください。それはプロセスを遅くします。変換すると、DF全体がRDDに変換され、空かどうかが確認されます。DFに数百万の行がある場合、RDD自体への変換には時間がかかります。
Nandakishore 2016年

3
.rddはプロセスを非常に遅くします
Raul H

14

あなたはの利点を取ることができますhead()(またはfirst()かどうかを確認するために)関数DataFrame単一の行を持っています。もしそうなら、それは空ではありません。


10
データフレームが空の場合、「java.util.NoSuchElementException:next on empty iterator」をスローします。[Spark 1.3.1]
FelixHo 2016年

6

Spark 2.4.0以降にありDataset.isEmptyます。

それの実装は:

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

a DataFrameはもはやScalaのクラスではなく、単なる型のエイリアス(おそらくSpark 2.0で変更された)であることに注意してください。

type DataFrame = Dataset[Row]

1
isEmptyはdf.head(1).isEmptyよりも遅い
Sandeep540

@ Sandeep540本当に?基準?提案は少なくとも1つの行をインスタンス化します。Sparkの実装は数値を転送するだけです。head()はlimit()も使用しています。groupBy()は実際には何も実行していません。count()を提供するRelationalGroupedDatasetを取得する必要があります。したがって、それが大幅に遅くなることはありません。多くの列(おそらく非正規化されたネストされたデータ)を含むデータセットの場合は、おそらくより高速です。ちなみに、あまり入力しないでください:-)
ベリリウム

5

Javaユーザーの場合、これをデータセットで使用できます。

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

これにより、考えられるすべてのシナリオがチェックされます(empty、null)。


5

する場合df.count > 0。すべてのエグゼキューター全体のすべてのパーティションの数を取得し、それらをドライバーで合計します。何百万もの行を処理する場合、これにはしばらく時間がかかります。

これを行う最良の方法はdf.take(1)、そのnull を実行して確認することです。これはjava.util.NoSuchElementException試してみるのにとても良いでしょうdf.take(1)

take(1)空の行の代わりにデータフレームが完了すると、エラーが返されます。エラーをスローする特定のコード行を強調表示しました。

ここに画像の説明を入力してください


1
何百万ものレコードを持つ大規模なデータフレームでこれを実行する場合、そのcount方法には時間がかかります。
TheM00s3 2016年

2
私は同じことを言った、なぜあなたがイマイチを下したのかわからない。
Nandakishore 2016年

あなたの権利はあなたが同じことを言った、残念ながら私はあなたに反対票を投じなかった。
TheM00s3 2016年

ああ大丈夫。TheMoos3は申し訳ありませんが、それをした人はだれでも答えを観察し、概念を理解してください。
Nandakishore 2016年

dfが空のときにdf.take(1)を使用すると、nullと比較できない空のROWが返されます
LetsPlayYahtzee

3

Scalaでは、暗黙を使用してメソッドとDataFrame API を追加できます。これにより、コードが読みやすくなります。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
  }
}

ここでは、他のメソッドも追加できます。暗黙的な変換を使用するimport DataFrameExtensions._には、拡張機能を使用するファイルでを使用します。その後、メソッドはそのまま次のように使用できます。

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

2

同じ質問があり、3つの主な解決策をテストしました:

  1. df!= null df.count> 0
  2. df.head(1).isEmpty()@ hulin003の提案
  3. @Justin Pihonyが示唆するdf.rdd.isEmpty

そしてもちろん3つは動作しますが、パフォーマンスに関しては、実行時間に関して、マシンの同じDFでこれらのメソッドを実行したときに次のことがわかりました。

  1. それは〜9366msかかります
  2. それは〜5607msかかります
  3. それは〜1921msかかります

したがって、@ Justin Pihonyが示唆するように、最善の解決策はdf.rdd.isEmptyだと思います


1
オプション3は時間がかかりませんが、なぜ2番目ですか?
thinkman


好奇心から...これはどのサイズのDataFramesでテストされましたか?
aiguofer

1

私はいくつかのケースでそれを発見しました:

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

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

これは「長さ」と同じか、take()をhead()に置き換えます

【解決方法】使用できる問題について。

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


1

PySparkで、あなたもこれを使用することができbool(df.head(1))得ることTrueFalse価値を

それは返すFalseデータフレームに行がない場合


0
df1.take(1).length>0

takeこの方法は、アレイ・サイズがゼロに等しくなるようにすれば、行の配列を返し、にはレコードが存在しませんdf


-1

dataframe.limit(1).count > 0

これもジョブをトリガーしますが、1つのレコードを選択しているため、10億規模のレコードの場合でも、時間の消費ははるかに少なくなる可能性があります。

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


これらはすべて、ほぼ同じ時間がかかる悪いオプションです
Pushpendra Jaiswal

@PushpendraJaiswalはい、そして悪いオプションの世界では、最良の悪いオプションを選択すべきです
ジョーダンモリス

-2

あなたはそれを次のように行うことができます:

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

1
これまでに戻るためにschema、2つのデータフレーム(sqlContext.emptyDataFramedf)が同じである必要はありませんtrueか?
y2k-shubham 2018年

1
これは機能しません。eqから継承され、引数(that)がレシーバーオブジェクト(this)への参照であるかどうかAnyRefテストします。
Alper t。ターカー2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.