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))얻을 수 True의 False값을

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.