Antworten:
Für Spark 2.1.0 würde ich vorschlagen, head(n: Int)
oder take(n: Int)
mit zu verwenden isEmpty
, je nachdem, was für Sie die klarste Absicht ist.
df.head(1).isEmpty
df.take(1).isEmpty
mit Python-Äquivalent:
len(df.head(1)) == 0 # or bool(df.head(1))
len(df.take(1)) == 0 # or bool(df.take(1))
Mit df.first()
und df.head()
geben beide zurück, java.util.NoSuchElementException
wenn der DataFrame leer ist. first()
ruft head()
direkt an, was anruft head(1).head
.
def first(): T = head()
def head(): T = head(1).head
head(1)
Gibt ein Array zurück. Wenn Sie head
dieses Array java.util.NoSuchElementException
übernehmen, ist der DataFrame leer.
def head(n: Int): Array[T] = withAction("head", limit(n).queryExecution)(collectFromPlan)
Anstatt also aufzurufen head()
, verwenden Sie head(1)
direkt, um das Array abzurufen, und dann können Sie es verwenden isEmpty
.
take(n)
ist auch gleichbedeutend mit head(n)
...
def take(n: Int): Array[T] = head(n)
Und limit(1).collect()
ist äquivalent zu head(1)
(Hinweis limit(n).queryExecution
in der head(n: Int)
Methode), daher sind alle folgenden äquivalent, zumindest soweit ich java.util.NoSuchElementException
das beurteilen kann, und Sie müssen keine Ausnahme abfangen, wenn der DataFrame leer ist.
df.head(1).isEmpty
df.take(1).isEmpty
df.limit(1).collect().isEmpty
Ich weiß, dass dies eine ältere Frage ist. Hoffentlich hilft sie jemandem, der eine neuere Version von Spark verwendet.
df.rdd.isEmpty
?
df.head(1)
es viel Zeit in Anspruch nimmt, liegt es wahrscheinlich daran, dass Ihr df
Ausführungsplan etwas Kompliziertes tut, das verhindert, dass Funken Verknüpfungen verwenden. Wenn Sie beispielsweise nur aus Parkettdateien lesen df = spark.read.parquet(...)
, bin ich mir ziemlich sicher, dass spark nur eine Dateipartition liest. Wenn Sie df
jedoch andere Dinge wie Aggregationen ausführen, erzwingen Sie möglicherweise versehentlich den Funken, einen großen Teil, wenn nicht alle Ihrer Quelldaten zu lesen und zu verarbeiten.
df.limit(1).count()
naiv verwendet. Bei großen Datenmengen dauert es viel länger als bei den von @ hulin003 gemeldeten Beispielen, die fast augenblicklich sind
Ich würde sagen, nur den Basiswert zu ergreifen RDD
. In Scala:
df.rdd.isEmpty
in Python:
df.rdd.isEmpty()
Davon abgesehen ist alles, was dies tut, ein Anruf take(1).length
, also wird es das Gleiche tun, wie Rohan geantwortet hat ... nur vielleicht etwas expliziter?
Sie können die head()
(oder first()
) Funktionen nutzen, um festzustellen, ob das DataFrame
eine einzelne Zeile hat. Wenn ja, ist es nicht leer.
Seit Spark 2.4.0 gibt es Dataset.isEmpty
.
Die Implementierung ist:
def isEmpty: Boolean =
withAction("isEmpty", limit(1).groupBy().count().queryExecution) { plan =>
plan.executeCollect().head.getLong(0) == 0
}
Beachten Sie, dass a DataFrame
in Scala keine Klasse mehr ist, sondern nur ein Typalias (wahrscheinlich mit Spark 2.0 geändert):
type DataFrame = Dataset[Row]
Für Java-Benutzer können Sie dies für einen Datensatz verwenden:
public boolean isDatasetEmpty(Dataset<Row> ds) {
boolean isEmpty;
try {
isEmpty = ((Row[]) ds.head(1)).length == 0;
} catch (Exception e) {
return true;
}
return isEmpty;
}
Dies überprüft alle möglichen Szenarien (leer, null).
Wenn du das tust df.count > 0
. Es zählt die Anzahl aller Partitionen aller Executoren und addiert sie bei Driver. Dies kann eine Weile dauern, wenn Sie mit Millionen von Zeilen arbeiten.
Der beste Weg, dies zu tun, besteht darin, durchzuführen df.take(1)
und zu überprüfen, ob es null ist. Dies wird java.util.NoSuchElementException
so besser zurückkehren, um es zu versuchen df.take(1)
.
Der Datenrahmen gibt einen Fehler zurück, wenn take(1)
er anstelle einer leeren Zeile ausgeführt wird. Ich habe die spezifischen Codezeilen hervorgehoben, in denen der Fehler ausgelöst wird.
count
Methode einige Zeit in Anspruch nehmen.
In Scala können Sie Implicits verwenden, um die Methoden isEmpty()
und nonEmpty()
die DataFrame-API hinzuzufügen, wodurch der Code ein bisschen besser lesbar wird.
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
}
}
Hier können auch andere Methoden hinzugefügt werden. Verwenden Sie import DataFrameExtensions._
in der Datei , in der Sie die erweiterte Funktionalität verwenden möchten, die implizite Konvertierung . Danach können die Methoden direkt wie folgt verwendet werden:
val df: DataFrame = ...
if (df.isEmpty) {
// Do something
}
Ich hatte die gleiche Frage und habe 3 Hauptlösungen getestet:
und natürlich funktionieren die 3, jedoch in Bezug auf die Leistung, hier ist, was ich gefunden habe, als ich diese Methoden auf demselben DF in meinem Computer in der Laufzeit der Ausführungszeit ausführte:
Daher denke ich, dass die beste Lösung df.rdd.isEmpty ist, wie @Justin Pihony vorschlägt
Ich fand das in einigen Fällen:
>>>print(type(df))
<class 'pyspark.sql.dataframe.DataFrame'>
>>>df.take(1).isEmpty
'list' object has no attribute 'isEmpty'
Dies gilt auch für "Länge" oder ersetzen Sie take () durch head ()
[Lösung] für das Problem, das wir verwenden können.
>>>df.limit(2).count() > 1
False
Wenn Sie Pypsark verwenden, können Sie auch Folgendes tun:
len(df.head(1)) > 0
dataframe.limit(1).count > 0
Dies löst auch einen Job aus, aber da wir einen einzelnen Datensatz auswählen, könnte der Zeitverbrauch selbst bei Datensätzen im Milliardenmaßstab viel geringer sein.
Sie können es wie folgt machen:
val df = sqlContext.emptyDataFrame
if( df.eq(sqlContext.emptyDataFrame) )
println("empty df ")
else
println("normal df")
schema
von zwei Datenrahmen ( sqlContext.emptyDataFrame
& df
) gleich ist, um jemals zurückzukehren true
?
eq
wird von geerbt AnyRef
und prüft, ob das Argument (das) eine Referenz auf das Empfängerobjekt (das) ist.