Spark / Scala: Как получить строки, которые находятся в Top X%? - PullRequest
0 голосов
/ 26 сентября 2019

У меня есть фрейм данных:

val df = Seq(
("q1", "a1", 0.31, "food"), ("q1", "a2", 0.01, "food"), ("q1", "a3", 0.51, "food"),
("q2", "b1", 0.01, "tools"), ("q2", "b2", 0.03, "tools"), ("q2", "b3", 0.01, "tools")
).toDF("id","part", "ratio", "category")
df.show(false)

+---+----+-----+--------+
|id |part|ratio|category|
+---+----+-----+--------+
|q1 |a1  |0.31 |food    |
|q2 |a2  |0.01 |food    |
|q3 |a3  |0.51 |food    |
|q4 |b1  |0.01 |tools   |
|q5 |b2  |0.03 |tools   |
|q6 |b3  |0.01 |tools   |
+---+----+-----+--------+

Я пытаюсь найти порог для каждой категории, не основываясь на выбросах в этой категории.Например, в продуктах питания 66% - больше 0,30, тогда как в инструментах почти все -> 0,0.Как мне найти пороги, чтобы большинство идентификаторов были в большем ведре.

Любой совет полезен.

Пробовал:

spark.sql("select category, percentile_approx(ratio, 0.2) as threshold from df group by category order by category").show(1000, false)

+--------+---------+
|category|threshold|
+--------+---------+
|food    |0.31     |
|tools   |0.01     |
+--------+---------+

Но проблема здесь в том, что мне нужно указать X, чтобы получить порог, но я ищу, как обнаружение выброса.

1 Ответ

1 голос
/ 26 сентября 2019

Этого можно добиться, определив диапазон допустимых данных с точки зрения среднего значения и стандартного отклонения, а затем выяснив строки, которые находятся за пределами допустимого диапазона

//define the acceptable range limits by looking at the mean and standard deviation    
val statsDF = df
          .groupBy("category")
          .agg(mean("ratio").as("mean"), stddev("ratio").as("stddev"))
          .withColumn("UpperLimit", col("mean") + col("stddev")*3)
          .withColumn("LowerLimit", col("mean") - col("stddev")*3).drop("mean","stddev")

// join statsDF with the original df and filter rows that are outside the acceptable range

val outliersDF= df.join(statsDF, usingColumns = Seq("category")).filter($"ratio"< $"LowerLimit" || $"ratio"> $"UpperLimit")

Я ссылался на этостатья для этого решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...