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)yja∑ja=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?


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


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


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)∑ja≠jot|xja-xjot|
μx

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)


; 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.