Прямо сейчас я должен использовать, 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).