Пытаетесь вычислить индекс Джини при распределении репутации StackOverflow?


11

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

грамм(S)знак равно1N-1(N+1-2(Σязнак равно1N(N+1-я)YяΣязнак равно1NYя))
NяYяя

Вот как я это реализовал (скопировано отсюда ):

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, учитывая, как репутация растет, чем больше у вас есть.

Я неосознанно игнорирую некоторые предположения о распределении репутации / пользователей?

Что я делаю не так?


Вы правы, но я не уверен, что понимаю, почему это должно повлиять на расчет?
yossale

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

@ Gung спасибо - я спрашиваю о расчете, а не о реализации SQL. Я напишу это в псевдокоде
yossale

Ответы:


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/calculation-gini-coefficient-in-bigquery-3bc162c82168


12

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

  1. NИкс
  2. Икс
  3. Икс
  4. NИксN×Σ
  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

Супер. Мне интересно знать, каково значение, поэтому, возможно, оставьте комментарий, когда вы сделали расчет!
Смиллиг

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

3×24×3,5

4

граммзнак равно2μN(N-1)ΣяJ|Икся-ИксJ|
μИкс

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 библиотеки Inq Gini (x)


; С t AS (ВЫБЕРИТЕ CAST (доход как плавающий) КАК x ИЗ # данных), tt AS (SELECT *, ROW_NUMBER () ПЕРЕВЕРНИТЕ (ЗАКАЗАТЬ ПО x) AS i ИЗ t) ВЫБЕРИТЕ 2.0 * SUM (x * i) / ( COUNT (x) * SUM (x)) - 1,0- (1,0 / COUNT (x)) КАК Джини ОТ tt
Крис
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.