Spark 데이터 프레임이 비어 있는지 확인하는 방법은 무엇입니까?


102

지금 은 비어 df.count > 0있는지 확인하는 데 사용해야 합니다 DataFrame. 그러나 그것은 비효율적입니다. 더 좋은 방법이 있습니까?

감사.

추신 : 비어 DataFrame있지 않은 경우 에만 저장하도록 비어 있는지 확인하고 싶습니다.

답변:


155

Spark 2.1.0의 경우 내 제안은 head(n: Int)또는 take(n: Int)함께 사용 isEmpty하는 것입니다.

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

파이썬에 상응하는 것 :

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

df.first()df.head()을 사용 java.util.NoSuchElementException하면 DataFrame이 비어 있는 경우 모두를 반환합니다 . first()호출 head()호출하는 직접 head(1).head.

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

head(1)Array를 반환하므로 head해당 Array를 사용하면 java.util.NoSuchElementExceptionDataFrame이 비어있을 때 발생합니다 .

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.NoSuchElementExceptionDataFrame가 비어있을 때 예외를.

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

나는 이것이 오래된 질문이라는 것을 알고 있으므로 새로운 버전의 Spark를 사용하는 사람에게 도움이되기를 바랍니다.


20
pyspark를 사용하는 사람들을 위해. isEmpty는 문제가 아닙니다. 대신 len (d.head (1))> 0을 수행하십시오.
AntiPawn79

5
이게 왜 더 낫지 df.rdd.isEmpty?
Dan Ciborowski-MSFT

1
df.head (1) .isEmpty는 시간이 많이 걸리고 이에 대한 다른 최적화 된 솔루션이 있습니다.
Rakesh Sabbani

1
@Rakesh Sabbani 안녕하세요, df.head(1)시간이 많이 걸리는 경우 아마도 귀하 df의 실행 계획이 스파크가 지름길을 사용하지 못하게하는 복잡한 일을하고 있기 때문일 것입니다 . 예를 들어, parquet 파일에서 읽는 df = spark.read.parquet(...)중이라면 Spark가 하나의 파일 파티션 만 읽을 것이라고 확신합니다. 그러나 df집계와 같은 다른 작업을 수행하는 경우 의도 치 않게 Spark가 소스 데이터의 전부는 아니더라도 많은 부분을 읽고 처리하도록 할 수 있습니다.
hulin003

내 경험을 AVOID에보고하는 것뿐입니다. 나는 df.limit(1).count()순진하게 사용하고있었습니다 . 큰 데이터 세트에서는 거의 즉각적인 @ hulin003에 의해보고 된 예보다 훨씬 더 많은 시간이 소요됩니다
Vzzarr

45

나는 단지 기본 RDD. Scala에서 :

df.rdd.isEmpty

파이썬에서 :

df.rdd.isEmpty()

즉,이 모든 작업은 call take(1).length이므로 Rohan이 대답 한 것과 동일한 작업을 수행 할 것입니다.


6
이것은 제 경우에 df.count () == 0보다 놀랍도록 느립니다
architectonic

2
rdd로 변환하는 것은 무거운 작업이 아닙니까?
Alok

1
별로. RDD는 여전히 대부분의 경우 Spark의 모든 것의 토대입니다.
Justin Pihony

28
df를 RDD로 변환하지 마십시오. 프로세스가 느려집니다. 변환하면 전체 DF를 RDD로 변환하고 비어 있는지 확인합니다. DF에 수백만 개의 행이 있다고 생각하면 RDD 자체로 변환하는 데 많은 시간이 걸립니다.
Nandakishore

3
.rdd는 프로세스 속도를 상당히 느리게합니다
Raul H

14

당신의 장점이 걸릴 수 있습니다 head()(또는 first()(가) 있는지 확인하기 위해) 기능을 DataFrame하나의 행이 있습니다. 그렇다면 비어 있지 않습니다.


10
데이터 프레임이 비어 있으면 "java.util.NoSuchElementException : next on empty iterator"가 발생합니다. [Spark 1.3.1]
FelixHo

6

만약 당신이 df.count > 0. 모든 실행기에서 모든 파티션의 수를 가져 와서 Driver에서 합산합니다. 수백만 개의 행을 처리 할 때 시간이 걸립니다.

이를 수행하는 가장 좋은 방법 df.take(1)은 null인지 확인 하고 수행하는 것 입니다. 이것은 java.util.NoSuchElementException시도를하는 것이 더 나아질 것 df.take(1)입니다.

데이터 프레임 take(1)은 빈 행 대신 완료 되면 오류를 반환합니다 . 오류가 발생하는 특정 코드 줄을 강조 표시했습니다.

여기에 이미지 설명 입력


1
수백만 개의 레코드가있는 방대한 데이터 프레임에서 이것을 실행하면 그 count방법은 시간이 걸릴 것입니다.
TheM00s3 2016

2
나는 똑같이 말했다. 왜 엄지 손가락을 내리 셨는지 모르겠습니다.
Nandakishore 2011

당신의 권리 당신은 똑같은 말을했지만 불행히도 나는 당신을 비하하지 않았습니다.
TheM00s3 2016

Ohhh 좋아. 미안하지만 TheMoos3를 한 사람은 대답을 관찰하고 개념을 이해하십시오.
Nandakishore 2016

df.take (1)을 사용하면 DF는 널 (null)와 비교할 수없는 빈 행을 다시 받고 빈 결과 때
LetsPlayYahtzee

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 정말? 기준? 제안은 하나 이상의 행을 인스턴스화합니다. Spark 구현은 숫자 만 전송합니다. head () 역시 limit ()을 사용하고 있으며 groupBy ()는 실제로 아무것도하지 않으며 count ()를 제공하는 RelationalGroupedDataset을 가져와야합니다. 따라서 속도가 크게 느려지지 않아야합니다. 많은 열을 포함하는 데이터 세트 (비정규 화 된 중첩 데이터)의 경우 더 빠를 수 있습니다. 더 적게 입력해야합니다. :-)
Beryllium

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).


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

나는 같은 질문이 있었고 세 가지 주요 솔루션을 테스트했습니다.

  1. df! = null df.count> 0
  2. @ hulin003이 제안한대로 df.head (1) .isEmpty ()
  3. @Justin Pihony가 제안한대로 df.rdd.isEmpty

물론 세 가지 작업은 성능 측면에서 볼 때 실행 시간 측면에서 내 컴퓨터의 동일한 DF에서 이러한 메서드를 실행할 때 찾은 결과입니다.

  1. ~ 9366ms 소요
  2. ~ 5607ms 소요
  3. ~ 1921ms 소요

따라서 @Justin Pihony제안한 것처럼 가장 좋은 솔루션은 df.rdd.isEmpty 라고 생각합니다.


1
옵션 3은 시간이 덜 걸리는데 왜 두 번째가 필요합니까?
thinkman

죄송합니다, 맞습니다, 저는 세 번째를 사용하고 있습니다. 응답을 업데이트합니다
aName

호기심에서 ... 어떤 크기의 DataFrame으로 테스트 되었습니까?
aiguofer

1

어떤 경우에는 다음을 발견했습니다.

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

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

이것은 "length"에 대해 동일하거나 take ()를 head ()로 대체합니다.

[해결책] 우리가 사용할 수있는 문제에 대해.

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

1

Pypsark를 사용하는 경우 다음을 수행 할 수도 있습니다.

len(df.head(1)) > 0

1

PySpark에, 당신은이를 사용할 수 있습니다 bool(df.head(1))얻을 수 TrueFalse값을

False데이터 프레임에 행이 없으면 반환 됩니다.


0
df1.take(1).length>0

take메서드는 행 배열을 반환하므로 배열 크기가 0이면에 레코드가없는 것입니다 df.


-1

dataframe.limit(1).count > 0

이것은 또한 작업을 트리거하지만 단일 레코드를 선택하기 때문에 10 억 스케일 레코드의 경우에도 시간 소비가 훨씬 낮을 수 있습니다.

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


이 모든 것은 거의 동일한 시간이 걸리는 나쁜 옵션입니다
Pushpendra Jaiswal

@PushpendraJaiswal 그렇습니다. 나쁜 옵션의 세계에서 우리는 최선의 나쁜 옵션을 선택해야합니다
Jordan Morris

-2

다음과 같이 할 수 있습니다.

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

1
반환하려면 schema두 데이터 프레임 ( sqlContext.emptyDataFrame& df)이 동일 해야하지 true않습니까?
y2k-shubham

1
작동하지 않습니다. eq에서 상속 AnyRef인수 (즉,)를 리시버 대상 (이)에 대한 참조인지 여부를 테스트한다.
Alper t. Turker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.