Próbujesz obliczyć indeks Gini w dystrybucji reputacji StackOverflow?

11

Próbuję obliczyć indeks Gini dla dystrybucji reputacji SO za pomocą SO Data Explorer. Równanie, które próbuję zaimplementować, jest następujące: Gdzie:n= liczba użytkowników w witrynie; i= identyfikator seryjny użytkownika (1 - 1 225 000); yi= reputacja użytkownikai.

sol(S.)=1n-1(n+1-2)(ja=1n(n+1-ja)yjaja=1nyja))
njayjaja

Oto jak to zaimplementowałem (skopiowałem stąd ):

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

Mój wynik wynosi (obecnie) -0,53, ale nie ma sensu: nawet nie jestem pewien, jak mógłby stać się ujemny, a nawet w wartości abs, spodziewałbym się, że nierówność będzie znacznie bliższa 1, biorąc pod uwagę, jak reputacja rośnie, tym więcej masz.

Czy nieświadomie ignoruję pewne założenia dotyczące rozpowszechniania reputacji / użytkowników?

Co robię źle?

yossale
źródło
Masz rację, ale nie jestem pewien, czy rozumiem, dlaczego powinno to wpłynąć na obliczenia?
yossale,
3
Zgaduję, że twoje pytanie dotyczy natury i obliczeń indeksu Gini, a nie tego, jak zaimplementować to w SQL (popraw mnie, jeśli się mylę). Jeśli to drugie, powinniśmy migrować to do SO. Kontynuując moje założenie, skopiowałem twój kod z witryny z danymi SE, ale może to pomóc, jeśli możesz przepisać go w pseudokodzie dla tych, którzy mogą nie czytać dobrze SQL.
gung - Przywróć Monikę
@ dziękuję - pytam o obliczenia, a nie implementację SQL. Napiszę go pseudo kodem
yossale

Odpowiedzi:

1

Oto jak możesz to obliczyć za pomocą 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

Wyjaśnienie znajduje się tutaj https://medium.com/@medvedev1088/calculating-gini-coefficient-in-bigquery-3bc162c82168

medvedev1088
źródło
12

Nie mogę SQLbardzo łatwo odczytać kodu, ale jeśli to pomoże, gdybym miał obliczyć współczynnik Giniego, zrobiłbym to (po prostu po angielsku).

  1. nx
  2. x
  3. x
  4. nxn×
  5. 1-(1/n)
  6. Voila!

Te kroki zacząłem od niezwykle prostego kodu w Rfunkcji (w pakiecie ineq ) do obliczenia współczynnika Giniego. Dla przypomnienia, oto ten kod:

> 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>

Wygląda nieco podobnie do twojego SQLkodu, ale tak jak powiedziałem, tak naprawdę nie mogę tak łatwo odczytać!

smillig
źródło
Dziękuję bardzo ! Brakowało mi części sortowania! to wiele wyjaśnia ...
yossale
Wspaniały. Chciałbym wiedzieć, jaka jest wartość, więc może zostaw komentarz, kiedy dokonasz obliczeń!
smillig
Cóż, kiedy sumuję wartości (tj. Jeśli jest 10 osób, z 1,3 lub 5 punktami, to mam tylko 3 stopnie: 1: 3,2: 5,3: 10) i pomnożę (ile z tym wynikiem) * wynik * (ranga wyniku) Dostałem -0,98, co miałoby sens, gdyby nie zły znak. Ale nie jestem pewien, jak mój mały skrót wpływa na skalę gini
yossale
3)×2)4×3.5
4

sol=2)μn(n-1)jajot|xja-xjot|
μx
StasK
źródło
1

Dodanie do odpowiedzi @smillig na podstawie podanego równania:

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

Dałem mi na moim zestawie testowym:

0,45503253636587840

Który jest taki sam jak ineq bibliotek R Gini (x)

Chris
źródło
; Z t AS (WYBIERZ CAST (dochód 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) * SUMA (x)) - 1,0 - (1,0 / COUNT (x)) JAKO gini FROM tt
Chris