Réponses:
Pour Spark 2.1.0, ma suggestion serait d'utiliser head(n: Int)ou take(n: Int)avec isEmpty, celui qui a l'intention la plus claire pour vous.
df.head(1).isEmpty
df.take(1).isEmpty
avec l'équivalent Python:
len(df.head(1)) == 0 # or bool(df.head(1))
len(df.take(1)) == 0 # or bool(df.take(1))
Utiliser df.first()et df.head()renverra tous les deux le java.util.NoSuchElementExceptionsi le DataFrame est vide. first()appelle head()directement, qui appelle head(1).head.
def first(): T = head()
def head(): T = head(1).head
head(1)renvoie un Array, donc prendre headcet Array provoque le java.util.NoSuchElementExceptionlorsque le DataFrame est vide.
def head(n: Int): Array[T] = withAction("head", limit(n).queryExecution)(collectFromPlan)
Donc, au lieu d'appeler head(), utilisez head(1)directement pour obtenir le tableau et vous pouvez ensuite utiliser isEmpty.
take(n)équivaut également à head(n)...
def take(n: Int): Array[T] = head(n)
Et limit(1).collect()est équivalent à head(1)(remarquez limit(n).queryExecutiondans la head(n: Int)méthode), donc les éléments suivants sont tous équivalents, du moins d'après ce que je peux dire, et vous n'aurez pas à attraper une java.util.NoSuchElementExceptionexception lorsque le DataFrame est vide.
df.head(1).isEmpty
df.take(1).isEmpty
df.limit(1).collect().isEmpty
Je sais que c'est une question plus ancienne, donc j'espère qu'elle aidera quelqu'un à utiliser une version plus récente de Spark.
df.rdd.isEmpty?
df.head(1)prend beaucoup de temps, c'est probablement parce que votre dfplan d'exécution fait quelque chose de compliqué qui empêche Spark de prendre des raccourcis. Par exemple, si vous lisez simplement des fichiers parquet df = spark.read.parquet(...), je suis presque sûr que Spark ne lira qu'une seule partition de fichiers. Mais si vous dffaites d'autres choses comme des agrégations, vous pouvez forcer par inadvertance Spark à lire et à traiter une grande partie, sinon la totalité, de vos données sources.
df.limit(1).count()naïvement. Sur les grands ensembles de données, cela prend beaucoup plus de temps que les exemples rapportés par @ hulin003 qui sont presque instantanés
Je dirais simplement de saisir le sous-jacent RDD. Dans Scala:
df.rdd.isEmpty
en Python:
df.rdd.isEmpty()
Cela étant dit, tout cela ne fait qu'appeler take(1).length, donc ça fera la même chose que Rohan a répondu ... juste peut-être un peu plus explicite?
Vous pouvez profiter des fonctions head()(ou first()) pour voir si le DataFramea une seule ligne. Si c'est le cas, il n'est pas vide.
Si vous le faites df.count > 0. Il prend le décompte de toutes les partitions sur tous les exécuteurs et les additionne dans Driver. Cela prend un certain temps lorsque vous traitez des millions de lignes.
La meilleure façon de faire est d'effectuer df.take(1)et de vérifier si sa valeur null. Cela reviendra java.util.NoSuchElementExceptiontellement mieux de faire un essai df.take(1).
Le dataframe renvoie une erreur quand take(1)est terminé au lieu d'une ligne vide. J'ai mis en évidence les lignes de code spécifiques où cela génère l'erreur.
countméthode prendra un certain temps.
Depuis Spark 2.4.0, il existe Dataset.isEmpty.
def isEmpty: Boolean =
withAction("isEmpty", limit(1).groupBy().count().queryExecution) { plan =>
plan.executeCollect().head.getLong(0) == 0
}
Notez que a DataFramen'est plus une classe dans Scala, c'est juste un alias de type (probablement changé avec Spark 2.0):
type DataFrame = Dataset[Row]
Pour les utilisateurs Java, vous pouvez l'utiliser sur un ensemble de données:
public boolean isDatasetEmpty(Dataset<Row> ds) {
boolean isEmpty;
try {
isEmpty = ((Row[]) ds.head(1)).length == 0;
} catch (Exception e) {
return true;
}
return isEmpty;
}
Cela vérifie tous les scénarios possibles (vide, nul).
Dans Scala, vous pouvez utiliser des implicits pour ajouter les méthodes isEmpty()et nonEmpty()à l'API DataFrame, ce qui rendra le code un peu plus agréable à lire.
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
}
}
Ici, d'autres méthodes peuvent également être ajoutées. Pour utiliser la conversion implicite, utilisez import DataFrameExtensions._dans le fichier que vous souhaitez utiliser la fonctionnalité étendue. Ensuite, les méthodes peuvent être utilisées directement comme suit:
val df: DataFrame = ...
if (df.isEmpty) {
// Do something
}
J'avais la même question, et j'ai testé 3 solutions principales:
et bien sûr les 3 fonctionnent, cependant en terme de performance, voici ce que j'ai trouvé, en exécutant ces méthodes sur le même DF dans ma machine, en terme de temps d'exécution:
donc je pense que la meilleure solution est df.rdd.isEmpty comme le suggère @Justin Pihony
J'ai trouvé cela sur certains cas:
>>>print(type(df))
<class 'pyspark.sql.dataframe.DataFrame'>
>>>df.take(1).isEmpty
'list' object has no attribute 'isEmpty'
c'est la même chose pour "length" ou remplacez take () par head ()
[Solution] pour le problème que nous pouvons utiliser.
>>>df.limit(2).count() > 1
False
Si vous utilisez Pypsark, vous pouvez également faire:
len(df.head(1)) > 0
dataframe.limit(1).count > 0
Cela déclenche également un travail, mais comme nous sélectionnons un enregistrement unique, même dans le cas d'un milliard d'enregistrements à l'échelle, la consommation de temps pourrait être beaucoup plus faible.
Vous pouvez le faire comme:
val df = sqlContext.emptyDataFrame
if( df.eq(sqlContext.emptyDataFrame) )
println("empty df ")
else
println("normal df")
schemadeux dataframes ( sqlContext.emptyDataFrame& df) soient identiques pour pouvoir revenir true?
eqest hérité de AnyRefet teste si l'argument (that) est une référence à l'objet récepteur (this).