Намагаєтеся обчислити індекс Джині для розподілу репутації StackOverflow?


11

Я намагаюся обчислити індекс Джині для розподілу репутації SO за допомогою SO Data Explorer. Рівняння, яке я намагаюся реалізувати, таке: Де: = кількість користувачів на сайті; = серійний ідентифікатор користувача (1 - 1,225,000); = репутація користувача .niyii

G(S)=1n1(n+12(i=1n(n+1i)yii=1nyi))
niyii

Ось як я його реалізував (скопіював звідси ):

DECLARE @numUsers int
SELECT @numUsers = COUNT(*) FROM Users
DECLARE @totalRep float
SELECT @totalRep = SUM(Users.Reputation) FROM Users
DECLARE @giniNominator float
SELECT @giniNominator = SUM( (@numUsers + 1 - CAST(Users.Id as Float)) * 
                              CAST(Users.Reputation as Float)) FROM Users
DECLARE @giniCalc float
SELECT @giniCalc = (@numUsers + 1 - 2*(@giniNominator / @totalRep)) / @numUsers
SELECT @giniCalc

Мій результат (наразі) -0,53, але це не має сенсу: я навіть не впевнений, як це могло б стати негативним, і навіть в абс-значеннях, я б очікував, що нерівність буде набагато ближче до 1, враховуючи, наскільки репутація росте, тим більше у вас є.

Я несвідомо ігнорую якесь припущення щодо розподілу репутації / користувачів?

Що я роблю неправильно?


Ви маєте рацію, але я не впевнений, що розумію, чому це має вплинути на розрахунок?
йоссал

3
Я здогадуюсь, що ваше запитання стосується природи та обчислення індексу Джині, а не про те, як реалізувати це в SQL (виправте мене, якщо я помиляюся). Якщо останні, ми повинні перенести це на SO. Продовжуючи з мого припущення, я скопіював ваш код з веб-сайту даних SE, але це може допомогти, якщо ви також можете переписати його в псевдо-код для тих, хто не може добре читати SQL.
gung - Відновіть Моніку

@gung спасибі - я запитую про розрахунок, а не про реалізацію SQL. Я
перепишу

Відповіді:


1

Ось як можна обчислити його за допомогою SQL:

with balances as (
    select '2018-01-01' as date, balance
    from unnest([1,2,3,4,5]) as balance -- Gini coef: 0.2666666666666667
    union all
    select '2018-01-02' as date, balance
    from unnest([3,3,3,3]) as balance -- Gini coef: 0.0
    union all
    select '2018-01-03' as date, balance
    from unnest([4,5,1,8,6,45,67,1,4,11]) as balance -- Gini coef: 0.625
),
ranked_balances as (
    select date, balance, row_number() over (partition by date order by balance desc) as rank
    from balances
)
SELECT date, 
    -- (1 − 2B) https://en.wikipedia.org/wiki/Gini_coefficient
    1 - 2 * sum((balance * (rank - 1) + balance / 2)) / count(*) / sum(balance) AS gini
FROM ranked_balances
GROUP BY date
ORDER BY date ASC
-- verify here http://shlegeris.com/gini

Пояснення тут https://medium.com/@medvedev1088/calculating-gini-coefficient-in-bigquery-3bc162c82168


12

Я не можу прочитати SQLкод дуже легко, але якщо це допоможе, якби я збирався обчислити коефіцієнт Джині, це я б робив (простою англійською мовою).

  1. nx
  2. x
  3. x
  4. nxn×
  5. 1(1/n)
  6. Вуаля!

Я зробив ці кроки із надзвичайно прямого коду у Rфункції (у пакунку ineq ) для обчислення коефіцієнта Джині. Для запису ось цей код:

> ineq::Gini
function (x) 
{
    n <- length(x)
    x <- sort(x)
    G <- sum(x * 1:n)
    G <- 2 * G/(n * sum(x))
    G - 1 - (1/n)
}
<environment: namespace:ineq>

Він схожий на ваш SQLкод, але, як я вже сказав, я не можу дуже легко це прочитати!


Дуже дякую ! Я пропустив сортувальну частину! це багато що пояснює ...
yossale

Супер. Мені цікаво дізнатися, що таке значення, тож можливо залиште коментар, коли ви зробили розрахунок!
smillig

Ну, коли я агрегував значення (тобто якщо є 10 людей, або 1,3, або 5 балів, то у мене є лише 3 ранги: 1: 3,2: 5,3: 10) і помножив (на скільки з цим рахунком) * оцінка * (ранг балу) Я отримав -0,98, що мало б сенсу, якби не той неправильний знак. Але я не впевнений, як мій маленький ярлик впливає на масштабність джині
yossale

3×24×3.5

4

G=2μn(n1)ij|xixj|
μx

1

Додавання до відповіді @smillig на основі наданого рівняння:

SELECT something AS x into #t FROM sometable
SELECT *,ROW_NUMBER() OVER(ORDER BY x) AS i INTO #tt FROM #t
SELECT 2.0*SUM(x*i)/(COUNT(x)*SUM(x))-1.0-(1.0/COUNT(x)) AS gini FROM #tt

Дав мені мій тестовий набір:

0,45503253636587840

Що таке саме, як і нерівні бібліотеки R Gini (x)


; З t AS (SELECT CAST (дохід AS FLOAT) AS x FROM #data), tt AS (SELECT *, ROW_NUMBER () OVER (ORDER BY x) AS i FROM t) SELECT 2.0 * SUM (x * i) / ( COUNT (x) * SUM (x)) - 1,0- (1,0 / COUNT (x)) AS gini ОТ tt
Кріс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.