Относительная частота Scala

#scala #spark-dataframe

#scala #apache-spark-sql

Вопрос:

У меня есть объект dataframe, который выглядит как:

  -- ---- ---- ---- ---- ---- ---- ---- ---- ---- -----  
|id|bin1|bin2|bin3|bin4|bin5|bin6|bin7|bin8|bin9|bin10|
 -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----- 
|a |   1|null|null|null|null|   1|  14|  91| 929| null|
|c |   4|   2|   5|  82|  49| 176| 222| 439|null| null|
|f |   1|   1|null|null|   2|   8| 226| 294|   2| null|
|e |null|   1|   2|null|   4|  13|  19| 242| 752|    1|
|y |   1|   1|   3|   9|  11|  17| 136| 664| 338| null|
|e |   4|   2|   1|   8|  14| 169| 952| 431|null| null|
  

Как я могу заменить абсолютные значения относительными значениями (частота)?

Редактировать: после преобразования объект dataframe для первой строки должен выглядеть следующим образом:

  -- ---- ---- ---- ---- ---- ---- ----- ------ ----- -----  
|id|bin1|bin2|bin3|bin4|bin5|bin6|bin7 |bin8  |bin9 |bin10|
 -- ---- ---- ---- ---- ---- ---- ----- ------ ----- ----- 
|a | 0.0|null|null|null|null| 0.0| 0.01|  0.09| 0.90| null|
  

Алгоритм должен делить каждое значение ячейки на сумму строк. После этого преобразования сумма строки всегда равна 1.

Я думаю, что могу достичь этого с помощью map, но я понятия не имею, как это сделать.

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

1. Было бы полезно, если бы вы могли показать, как должен выглядеть ожидаемый результат.

2. Спасибо за ваш комментарий. Я отредактировал свой пост и надеюсь, что это сделает его более понятным.

3. Можете ли вы добавить то, что вы пробовали до сих пор? И это домашнее задание?

4. @Jeremy: Я пробовал что-то вроде evan058, но мне не удалось создать столбец sum, потому что мой первый столбец — это столбец string. Но его пример помог мне решить эту проблему с помощью cols.tails. Собрать. В следующий раз я добавлю то, что уже пробовал. Это было бывшее домашнее задание, которое я мог решить. 🙂

5. Я имел в виду, что я не мог решить.

Ответ №1:

Предполагая, что вы хотите, чтобы null s обрабатывались как 0s, вот одно из решений:

 scala> var df = Seq((1d,2d,Double.NaN),(Double.NaN, 3d,4d), (5d, Double.NaN, 6d)).toDF("a", "b", "c")
df: org.apache.spark.sql.DataFrame = [a: double, b: double, c: double]

scala> df.show
 --- --- --- 
|  a|  b|  c|
 --- --- --- 
|1.0|2.0|NaN|
|NaN|3.0|4.0|
|5.0|NaN|6.0|
 --- --- --- 

scala> val cols = df.columns
cols: Array[String] = Array(a, b, c)

scala> import org.apache.spark.sql.DataFrameNaFunctions

scala> df = df.na.fill(0d).withColumn("sum", cols.map(col).reduce(_   _))
df: org.apache.spark.sql.DataFrame = [a: double, b: double, c: double, sum: double]

scala> df.show
 --- --- --- ---- 
|  a|  b|  c| sum|
 --- --- --- ---- 
|1.0|2.0|0.0| 3.0|
|0.0|3.0|4.0| 7.0|
|5.0|0.0|6.0|11.0|
 --- --- --- ---- 


scala> cols.foreach( cName => df = df.withColumn(cName, df.col(cName) / df.col("sum")))

scala> df.drop("sum").show
 ------------------- ------------------- ------------------ 
|                  a|                  b|                 c|
 ------------------- ------------------- ------------------ 
| 0.3333333333333333| 0.6666666666666666|               0.0|
|                0.0|0.42857142857142855|0.5714285714285714|
|0.45454545454545453|                0.0|0.5454545454545454|
 ------------------- ------------------- ------------------ 
  

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

1. Спасибо. Ваш пример мне очень помог.