Можно использовать функцию уменьшение набора данных.
Сначала мы определим функцию уменьшения, которая сравнивает попарно две строки. Результат для каждого столбца строк: либо null
(если значения в обеих строках для соответствующего столбца null
), либо 1
в противном случае.
def reduceNull(r1: Row, r2: Row): Row = {
Row.fromSeq(
for( i <- 0 to r1.length-1) yield if( r1.isNullAt(i) && r2.isNullAt(i) ) null else 1
)
}
Чтобы уменьшить объем данных В процессе обработки мы выбираем только те столбцы, в которых мы заинтересованы, а затем применяем функцию сокращения:
val fruitList = Seq("apple", "orange", "banana", "pear")
val resultRow = df.select(fruitList.head, fruitList.tail:_*)
.reduce(reduceNull _)
Результатом функции уменьшения является отдельная строка, содержащая в каждом столбце либо null
, либо * 1015. *, в зависимости от всех значений в этом столбце в исходном фрейме данных.
val colsWithAllRowsNull = (for( i <- 0 to resultRow.size-1) yield (fruitList(i), resultRow.get(i)))
.filter(e => e._2 == null)
.map(_._1)
.toList
println(colsWithAllRowsNull)
печатает
List(orange, pear)
EDIT : Оказалось, что для моей установки (Spark Standalone, 4 ядра, 2 линии данных Mio) использование Dataset.describe
занимает только половину времени функции уменьшения.