Прямо сейчас я должен использовать, df.count > 0чтобы проверить DataFrame, пуст или нет. Но это неэффективно. Есть ли лучший способ сделать это?
Спасибо.
PS: я хочу проверить, пуст ли он, чтобы я сохранял только, DataFrameесли он не пустой
Ответы:
Для 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если 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плане выполнения есть что-то сложное, что не позволяет Spark использовать ярлыки. Например, если вы просто читаете паркетные файлы df = spark.read.parquet(...), я уверен, что Spark будет читать только один файловый раздел. Но если вы dfделаете другие вещи, такие как агрегирование, вы можете непреднамеренно заставить Spark читать и обрабатывать большую часть, если не все, ваших исходных данных.
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'
это то же самое для "length" или заменить 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).