Применение условного усеченного среднего в скале - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь достичь 80% усеченного значения для каждой группы в скале, чтобы избавиться от выбросов. Но это применимо только в том случае, если количество записей в этой группе не менее 10.

Пример,

val sales = Seq(
  ("Warsaw", 2016, 100),
  ("Warsaw", 2017, 200),
  ("Boston", 2015, 50),
  ("Boston", 2016, 150),
  ("Toronto", 2017, 50)
).toDF("city", "year", "amount")

Так что в этом наборе данных, если я делаю группу по этому,

val groupByCityAndYear = sales
  .groupBy("city", "year").count() 
  .agg(avg($"amount").as("avg_amount"))

Таким образом, в этом случае, если число больше 10, то следует удалить выбросы (может быть усечено на 80%), иначе непосредственно avg ($ «сумма»). Как я могу достичь этого?

Вот правильное объяснение усеченного среднего, которое я получил, чтобы объяснить этот сценарий,

Подумайте, что означает усеченное значение: в прототипе вы сначала сортируете свои данные в порядке возрастания. Затем вы подсчитываете процент отсечения снизу и отбрасываете эти значения. Например, усеченное на 10% среднее является распространенным; в этом случае вы будете считать с самого низкого значения, пока не пройдете 10% всех данных в вашем наборе. Значения ниже этой отметки откладываются. Аналогично, вы начинаете обратный отсчет с самого высокого значения до тех пор, пока не пройдете процент обрезки, и отложите все значения выше этого значения. Теперь у вас осталось 80%. Вы берете среднее значение этого, и это ваше усредненное на 10% значение

1 Ответ

0 голосов
/ 12 мая 2018

Это можно сделать с помощью оконной функции, но будет дорого:

import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions.Window

val w = Window.partitionBy("city", "year").orderBy("amount")

sales
  .withColumn("rn", row_number().over(w))
  .withColumn("count", count("*").over(w))
  .groupBy("city", "year")
  .agg(avg(when(
    ($"count" < 10) or ($"rn" between($"count" * 0.1, $"count" * 0.9)), 
    $"amount"
  )) as "avg_amount")
...