Коэффициент корреляции Спирмена в MySQL - как рассчитать средний рейтинг? - PullRequest
0 голосов
/ 06 мая 2020

Как я могу рассчитать средний рейтинг равных значений?

Я пытаюсь написать запрос MySQL, который вычисляет коэффициент корреляции Спирмена. Моя идея состоит в том, чтобы написать запрос, который вычисляет коэффициент корреляции Пирсона и использует RANK () OVER (ORDER BY X) для ранжирования значений перед вычислением.

Мне удалось заставить это работать, см. Код ниже. Но моя проблема в том, что все значения, которые были одинаковыми до ранжирования, после ранжирования становятся одинаковыми. Мои исследования говорят мне, что равные значения должны получать средний рейтинг всех равных значений. Как это можно включить в мой запрос?

Мой код:

#setting values
SELECT
    @ax := avg(ranked_x) AS avg_x, 
    @ay := avg(ranked_y) AS avg_y,
    @div := (stddev_samp(ranked_x) * stddev_samp(ranked_y)) AS stddev
FROM
  (SELECT
      RANK() OVER(ORDER BY x) as ranked_x,
      RANK() OVER(ORDER BY y) as ranked_y
   FROM table) AS D;

#calculating the correlation coefficient with the values from the last query
SELECT
    sum( ( ranked_x - @ax ) * (ranked_y - @ay) ) / ((count(*) -1) * @div) AS correlation
FROM
   (SELECT
      RANK() OVER(ORDER BY x) as ranked_x,
      RANK() OVER(ORDER BY y) as ranked_y
   FROM table) AS D;

Пример:

Набор данных с отдельными значениями, такими как [2, 16, 27, 28, 42], будет ранжирован [1, 2, 3, 4, 5]. Набор данных с несколькими идентичными значениями, такими как [2, 2, 6, 6, 6], будет иметь рейтинг [1,5, 1,5, 4, 4, 4].

Это потому, что две двойки занимает первое и второе места, а среднее значение между 1 и 2 составляет 1,5. Три четверки - это числа 3, 4 и 5, и среднее из этих трех значений равно 4.

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Возможно, это поможет, кстати, что за скрипка?

DROP TABLE IF EXISTS T;
CREATE TABLE T
(VAL INT);
INSERT INTO  T VALUES
(2),(2),(6),(6),(6);

select t.val,aver
from t
join
(
select val, avg(rn) aver
from
(
SELECT VAL,
         row_number() over (order by val) rn
FROM T
) s
group by val
) s
on s.val = t.val
;

+------+--------+
| val  | aver   |
+------+--------+
|    2 | 1.5000 |
|    2 | 1.5000 |
|    6 | 4.0000 |
|    6 | 4.0000 |
|    6 | 4.0000 |
+------+--------+
5 rows in set (0.001 sec)
0 голосов
/ 06 мая 2020

На основе описания, представленного на Wiki: Коэффициент ранговой корреляции Спирмена :

WITH 
cte1 AS ( SELECT x,
                 y,
                 CAST(RANK() OVER(ORDER BY x) AS SIGNED) as ranked_x,
                 CAST(RANK() OVER(ORDER BY y) AS SIGNED) as ranked_y
          FROM src_table ),
cte2 AS ( SELECT x,
                 y,
                 ranked_x,
                 ranked_y,
                 ranked_x - ranked_y AS di,
                 (ranked_x - ranked_y) * (ranked_x - ranked_y) as di2
          FROM cte1 )
SELECT 1 - 6 * SUM(di2) / COUNT(*) / (COUNT(*) * COUNT(*) - 1) AS srcc
FROM cte2;

То же после сжатия:

WITH 
cte AS ( SELECT POW((CAST(RANK() OVER(ORDER BY x) AS SIGNED) - CAST(RANK() OVER(ORDER BY y) AS SIGNED)), 2) as di2
         FROM src_table )
SELECT 1 - 6 * SUM(di2) / COUNT(*) / (COUNT(*) * COUNT(*) - 1) AS srcc
FROM cte;

скрипка

...