Cerchi di calcolare l'indice Gini sulla distribuzione della reputazione StackOverflow?


11

Sto cercando di calcolare l'indice Gini sulla distribuzione della reputazione SO utilizzando SO Data Explorer. L'equazione che sto cercando di implementare è questa: Dove: = numero di utenti sul sito; = ID seriale utente (1 - 1.225.000); = reputazione dell'utente .niyii

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

Ecco come l'ho implementato (copiato da qui ):

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

Il mio risultato è (attualmente) -0,53, ma non ha senso: non sono sicuro nemmeno come possa essere diventato negativo, e anche in valore abs, mi sarei aspettato che la disuguaglianza fosse molto più vicina a 1, dato come la reputazione cresce più ce l'hai.

Sto inconsapevolmente ignorando alcune ipotesi sulla distribuzione della reputazione / degli utenti?

Cosa faccio di sbagliato?


Hai ragione, ma non sono sicuro di vedere perché questo dovrebbe influenzare il calcolo?
yossale,

3
Immagino che la tua domanda riguardi la natura e il calcolo dell'indice Gini e non su come implementarlo in SQL (correggimi se sbaglio). In quest'ultimo caso, dovremmo migrarlo su SO. Continuando con il mio presupposto, ho copiato il tuo codice dal sito di dati SE, ma potrebbe essere utile se puoi anche riscriverlo in pseudo-codice per coloro che potrebbero non leggere bene SQL.
gung - Ripristina Monica

@gung grazie - chiedo del calcolo, non dell'implementazione SQL. Lo scriverò in pseudo codice
yossale il

Risposte:


1

Ecco come puoi calcolarlo con 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

La spiegazione è qui https://medium.com/@medvedev1088/calculating-gini-coefficient-in-bigquery-3bc162c82168


12

Non riesco a leggere il SQLcodice molto facilmente, ma se aiuta, se volessi calcolare il coefficiente Gini, questo è quello che farei (in un inglese semplice).

  1. Capire la di (cioè il numero di persone con rappresentante su SO)xnx
  2. Ordina dal più basso al più altox
  3. Somma ogni moltiplicata per il suo ordine nella classifica (cioè se ci sono 10 persone, il rappresentante per la persona con il rappresentante più basso viene moltiplicato per 1 e il rappresentante della persona con il rappresentante più alto viene moltiplicato per 10)x
  4. Prendi quel valore e dividilo per il prodotto di e la somma di (cioè rep) e quindi moltiplica quel risultato per 2x n × nxn×
  5. Prendi quel risultato e sottrai il valore di da esso.1(1/n)
  6. Ecco!

Ho preso quei passaggi dal codice notevolmente diretto nella Rfunzione (nel pacchetto ineq ) per il calcolo del coefficiente di Gini. Per la cronaca, ecco quel codice:

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

Sembra in qualche modo simile al tuo SQLcodice, ma come ho detto, non riesco davvero a leggerlo molto facilmente!


Ringrazia molto molto! Ho perso la parte di smistamento! questo spiega molto ...
yossale,

Super. Sono interessato a sapere qual è il valore, quindi forse lascia un commento quando hai fatto il calcolo!
smillig

Bene, quando ho aggregato i valori (cioè se ci sono 10 persone, con 1,3 o 5 punti, allora ho solo 3 gradi: 1: 3,2: 5,3: 10) e moltiplicato il (quante con quel punteggio) * punteggio * (grado del punteggio) Ho ottenuto -0,98, che avrebbe avuto senso se non fosse stato per il segno sbagliato. Ma non sono sicuro di come la mia piccola scorciatoia influenzi la scala gini
yossale,

Non dovresti assegnare il punteggio medio? Vale a dire per 1: 3 applicare , per 2: 5 applicare ecc.? O l'hai fatto? 4 × 3.53×24×3.5
Björn

4

Ci sono, credo, quattro formulazioni equivalenti dell'indice Gini. Per me, il più naturale è una statistica U: dove è la media di 's. Puoi ricontrollare i tuoi calcoli con questa formula. Ovviamente, il risultato deve essere non negativo. Per quanto ne so degli indici Gini, la distribuzione della reputazione su CV dovrebbe avere l'indice Gini sopra 0.9; se 0,98 ha molto senso o no, non posso dire però.μx

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

1

Aggiunta alla risposta @smillig, in base all'equazione fornita:

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

Mi ha dato il mio set di test:

,45503253636587840

Che è lo stesso delle librerie ineq di R Gini (x)


; CON t AS (SELEZIONA CAST (reddito COME GALLEGGIANTE) AS x FROM #data), tt AS (SELECT *, ROW_NUMBER () OVER (ORDINA PER x) AS i DA t) SELEZIONA 2.0 * SUM (x * i) / ( COUNT (x) * SUM (x)) - 1.0- (1.0 / COUNT (x)) COME gini DA tt
Chris
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.