Печать уникальных значений в столбце в процентах от общего числа строк

#scala #apache-spark #apache-spark-sql #distinct

Вопрос:

Для одного из этапов очистки данных я хотел бы получить представление о том, как существуют уникальные значения в процентах от общего количества строк, чтобы я мог применить пороговое значение и решить, следует ли полностью удалить этот столбец / функцию. Для этого я придумал эту функцию, как показано ниже:

 def uniqueValuesAsPercentage(data: DataFrame) = {
  val (rowCount, columnCount) = shape(data)
  data.selectExpr(data.head().getValuesMap[Long](data.columns).map(elem => {
      val (columnName, uniqueCount) = elem
      val percentage = uniqueCount / rowCount * 100
      (columnName, uniqueCount, percentage) 
  }))
}
 

Но это не удается со следующей ошибкой:

 <console>:90: error: type mismatch;
 found   : scala.collection.immutable.Iterable[(String, Long, Long)]
 required: String
         data.selectExpr(data.head().getValuesMap[Long](data.columns).map(elem => {
 

К сожалению, поскольку это находится в записной книжке Apache Zeppelin, мне также не хватает возможностей IDE. У меня есть IntelliJ до конца, но поддержка инструментов больших данных, похоже, недоступна для моей версии IDE. Очень раздражает!

Есть какие-нибудь идеи относительно того, в чем здесь проблема? Я думаю, что я путаюсь с фреймом данных в selectExpr(….). Как видно, я возвращаю кортеж с информацией, которую я вычисляю.

Комментарии:

1. selectExpr получает строку, представляющую выражение sql ( cast(col_x as string) ), но вы предоставляете ей итерацию кортежей. Смотрите мое предлагаемое решение ниже.

Ответ №1:

Вы можете рассчитать это гораздо более простым способом:

 import org.apache.spark.sql.functions.{col, countDistinct, count}

import spark.implicits._

// define a dataframe for example
val data = Seq(("1", "1"), ("1", "2"), ("1", "3"), ("1", "4")).toDF("col_a", "col_b")

data.select(data.columns.map(c => (lit(100) * countDistinct(col(c)) / count(col(c))).alias(c)): _*).show()

// output:
 ----- ----- 
|col_a|col_b|
 ----- ----- 
| 25.0|100.0|
 ----- ----- 
 

Комментарии:

1. Показать-это хорошо, но есть ли возможность извлечь значения из фрейма данных?

2. @joesan конечно, используйте collect() вместо show() и назначьте результат в переменную.