Tentando calcular o índice Gini na distribuição de reputação do StackOverflow?

11

Estou tentando calcular o índice Gini na distribuição de reputação do SO usando o SO Data Explorer. A equação que estou tentando implementar é a seguinte: Onde: = número de usuários no site; = ID de série do usuário (1 - 1.225.000); = reputação do usuário .niyii

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

É assim que eu o implementei (copiado daqui ):

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

Meu resultado é (atualmente) -0,53, mas não faz sentido: não sei ao certo como isso pode ter se tornado negativo, e mesmo com o valor abs, eu esperava que a desigualdade estivesse muito mais próxima de 1, considerando a reputação cresce quanto mais você tem.

Ignoro, sem saber, algumas suposições sobre a distribuição da reputação / usuários?

O que eu faço de errado?

yossale
fonte
Você está certo, mas não sei ao certo por que isso deve afetar o cálculo?
usar o seguinte comando
3
Acho que sua pergunta é sobre a natureza e o cálculo do índice Gini, e não sobre como implementá-lo no SQL (me corrija se estiver errado). Neste último caso, devemos migrar isso para o SO. Continuando com minha suposição, copiei seu código do site de dados SE, mas pode ser útil se você também puder reescrevê-lo em pseudo-código para aqueles que podem não ler bem o SQL.
gung - Restabelece Monica
@gung obrigado - eu pergunto sobre o cálculo, não a implementação do SQL. Vou reescrevê-lo em pseudo-código
yossale

Respostas:

1

Aqui está como você pode calculá-lo com 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

A explicação está aqui https://medium.com/@medvedev1088/calculating-gini-coefficient-in-bigquery-3bc162c82168

medvedev1088
fonte
12

Não consigo ler o SQLcódigo com muita facilidade, mas se ajudar, se eu fosse calcular o coeficiente de Gini, é isso que eu faria (em inglês).

  1. Descobrir o de (ou seja, o número de pessoas com representante no SO)xnx
  2. Classificar do menor para o maiorx
  3. Soma cada multiplicado por sua ordem na classificação (ou seja, se houver 10 pessoas, o representante da pessoa com o representante mais baixo será multiplicado por 1 e o representante da pessoa com o representante mais alto será multiplicado por 10)x
  4. Pegue esse valor e divida-o pelo produto de e a soma de (ou seja, rep) e multiplique esse resultado por 2x n × nxn×
  5. Pegue esse resultado e subtraia o valor de dele.1(1/n)
  6. Voila!

Eu tomei essas medidas do código notavelmente direto na Rfunção (no pacote ineq ) para calcular o coeficiente de Gini. Para o registro, aqui está esse código:

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

Parece um pouco parecido com o seu SQLcódigo, mas como eu disse, não consigo ler muito facilmente!

smillig
fonte
Agradece muito muito! Perdi a parte da triagem! Isso explica muita coisa ...
yossale
Super. Estou interessado em saber qual é o valor, então talvez deixe um comentário quando você fizer o cálculo!
smillig
Bem, quando eu agreguei os valores (ou seja, se houver 10 pessoas, com 1,3 ou 5 pontos, então eu tenho apenas 3 classificações: 1: 3,2: 5,3: 10) e multipliquei o (quantas com essa pontuação) * pontuação * (classificação) obtive -0,98, o que faria sentido se não fosse o sinal errado. Mas eu não sei como meus pequenos efeitos de atalho a escala Gini
yossale
Você não precisaria atribuir a pontuação média? Ou seja, para 1: 3 aplique , pois 2: 5 aplique etc.? Ou você fez isso? 4 × 3,53×24×3.5
Björn
4

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

Adicionando à resposta @smillig, com base na equação fornecida:

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

Me deu no meu conjunto de testes:

0.45503253636587840

Que é o mesmo que as bibliotecas ineq de R Gini (x)

Chris
fonte
; WITH t AS (SELECIONAR CAST (renda COMO FLUTUAR) AS x FROM #dados), tt AS (SELECT *, ROW_NUMBER () OVER (ORDER BY x) AS i FROM t) SELECT 2.0 * SUM (x * i) / ( Contagem (x) * SOMA (x)) - 1.0- (1.0 / CONTAGEM (x)) AS gini FROM tt #
Chris