Відповіді:
Що стосується Spark 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()
і df.head()
поверне значення java.util.NoSuchElementException
if, якщо DataFrame порожній. 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
виняток, коли DataFrame порожній.
df.head(1).isEmpty
df.take(1).isEmpty
df.limit(1).collect().isEmpty
Я знаю, що це давнє запитання, тому, сподіваюся, це допоможе комусь, хто використовує новішу версію Spark.
df.rdd.isEmpty
?
df.head(1)
це забирає багато часу, це, мабуть, тому, що ваш df
план виконання робить щось складне, що заважає іскрі приймати ярлики. Наприклад, якщо ви просто читаєте з паркетних файлів df = spark.read.parquet(...)
, я впевнений, що іскра буде читати лише один розділ файлу. Але якщо ви df
робите інші речі, такі як агрегації, ви можете ненавмисно змусити іскру читати та обробляти значну частину, якщо не всіх, ваших вихідних даних.
df.limit(1).count()
наївно. На великих наборах даних це займає набагато більше часу, ніж наведені приклади @ hulin003, які майже миттєві
Я б сказав, щоб просто схопити основне RDD
. У Scala:
df.rdd.isEmpty
в Python:
df.rdd.isEmpty()
З take(1).length
огляду на це, все це робить виклик , тож буде робити те саме, що відповів Рохан ... лише, можливо, трохи більш чітко?
Ви можете скористатися перевагами head()
(або first()
) функцій, щоб побачити, чи DataFrame
є в одному рядку. Якщо так, це не пусте.
Якщо ви це зробите df.count > 0
. Він бере підрахунок усіх розділів у всіх виконавцях і додає їх у Driver. Це займає деякий час, коли ви маєте справу з мільйонами рядків.
Найкращий спосіб зробити це - виконати df.take(1)
та перевірити, чи є він нульовим. Це повернеться, java.util.NoSuchElementException
так що краще спробувати df.take(1)
.
Коли виконано, кадр даних повертає помилку take(1)
замість порожнього рядка. Я виділив конкретні рядки коду, де він видає помилку.
count
метод займе деякий час.
З 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]
Для користувачів Java ви можете використовувати це на наборі даних:
public boolean isDatasetEmpty(Dataset<Row> ds) {
boolean isEmpty;
try {
isEmpty = ((Row[]) ds.head(1)).length == 0;
} catch (Exception e) {
return true;
}
return isEmpty;
}
Це перевіряє всі можливі сценарії (порожній, нульовий).
У Scala ви можете використовувати імпліцити для додавання методів isEmpty()
та nonEmpty()
до API DataFrame, що зробить код трохи приємнішим для читання.
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
}
У мене було те саме питання, і я протестував 3 основні рішення:
і, звичайно, 3 роботи, однак з точки зору виконання, ось що я виявив, виконуючи ці методи на тому самому DF в моїй машині, в термін виконання:
тому я думаю, що найкращим рішенням є df.rdd.isEmpty, як пропонує @Justin Pihony
Я виявив, що в деяких випадках:
>>>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
Якщо ви використовуєте Pypsark, ви також можете зробити:
len(df.head(1)) > 0
dataframe.limit(1).count > 0
Це також запускає роботу, але оскільки ми вибираємо єдиний запис, навіть у випадку мільярдових записів масштабу споживання часу може бути набагато меншим.
Ви можете зробити це так:
val df = sqlContext.emptyDataFrame
if( df.eq(sqlContext.emptyDataFrame) )
println("empty df ")
else
println("normal df")
schema
два кадри даних ( sqlContext.emptyDataFrame
& df
) були однаковими, щоб колись повернутися true
?
eq
успадковується від AnyRef
і перевіряє, чи аргумент (that) є посиланням на об'єкт одержувача (this).