¿Intenta calcular el índice de Gini en la distribución de reputación de StackOverflow?

11

Estoy tratando de calcular el índice de Gini en la distribución de reputación SO usando SO Data Explorer. La ecuación que intento implementar es la siguiente: Donde: = número de usuarios en el sitio; = ID de serie del usuario (1 - 1,225,000); = reputación del usuario .n

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

Así es como lo implementé (copiado de aquí ):

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

Mi resultado es (actualmente) -0.53, pero no tiene sentido: ni siquiera estoy seguro de cómo podría haberse vuelto negativo, e incluso en valor abs, hubiera esperado que la desigualdad estuviera mucho más cerca de 1, dada la reputación crece cuanto más lo tienes.

¿Estoy ignorando sin saberlo alguna suposición sobre la distribución de la reputación / usuarios?

¿Qué hago mal?

yossale
fuente
Tienes razón, pero no estoy seguro de ver por qué esto debería afectar el cálculo.
yossale
3
Supongo que su pregunta es sobre la naturaleza y el cálculo del índice de Gini, y no sobre cómo implementar eso en SQL (corríjame si me equivoco). Si es lo último, deberíamos migrar esto a SO. Continuando con mi suposición, he copiado su código del sitio de datos de SE, pero podría ayudar si también puede reescribirlo en pseudocódigo para aquellos que no leen bien SQL.
gung - Restablece a Monica
@gung gracias - Pregunto sobre el cálculo, no la implementación de SQL. Lo volveré a escribir en pseudocódigo
yossale el

Respuestas:

1

Aquí es cómo puede calcularlo 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 explicación está aquí https://medium.com/@medvedev1088/calculating-gini-coefficient-in-bigquery-3bc162c82168

medvedev1088
fuente
12

No puedo leer el SQLcódigo muy fácilmente, pero si me ayuda, si fuera a calcular el coeficiente de Gini, esto es lo que haría (en inglés).

  1. Calcule el de (es decir, el número de personas con rep en SO)xnx
  2. Ordenar de menor a mayorx
  3. Suma cada multiplicado por su orden en el rango (es decir, si hay 10 personas, el representante de la persona con el representante más bajo se multiplica por 1 y el representante de la persona con el representante más alto se multiplica por 10)x
  4. Tome ese valor y divídalo por el producto de y la suma de (es decir, rep) y luego multiplique ese resultado por 2x n × nxn×
  5. Tome ese resultado y reste el valor de .1(1/n)
  6. Voila!

Tomé esos pasos del código notablemente directo en la Rfunción (en el paquete ineq ) para calcular el coeficiente de Gini. Para el registro, aquí está ese 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>

Se ve algo similar a su SQLcódigo, pero como dije, ¡realmente no puedo leer eso muy fácilmente!

smillig
fuente
Le da las gracias muy mucho! Me perdí la parte de clasificación! eso explica mucho ...
yossale
Súper. Estoy interesado en saber cuál es el valor, así que tal vez deje un comentario cuando haya realizado el cálculo.
smillig
Bueno, cuando agregué los valores (es decir, si hay 10 personas, con 1,3 o 5 puntos, entonces tengo solo 3 rangos: 1: 3,2: 5,3: 10) y multipliqué el (cuántos con ese puntaje) * puntaje * (rango de puntaje) Obtuve -0.98, lo que habría tenido sentido si no fuera por el signo equivocado. Pero no estoy seguro de cómo mi pequeño atajo afecta la escala de
Gini
¿No tendría que asignar el puntaje promedio? Es decir, para 1: 3 aplicar , para 2: 5 aplicar etc. ¿O hiciste eso? 4 × 3.53×24×3.5
Björn
4

Hay, creo, cuatro formulaciones equivalentes del índice de Gini. Para mí, el más natural es una estadística U: donde es la media de 's. Puede verificar sus cálculos con esta fórmula. Obviamente, el resultado debe ser no negativo. Por lo que sé sobre los índices de Gini, la distribución de reputación en CV debería tener el índice de Gini por encima de 0.9; si 0.98 tiene mucho sentido o no, no puedo decirlo.μx

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

Agregando a la respuesta @smillig, basado en la ecuación provista:

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 dio en mi conjunto de prueba:

0.45503253636587840

Que es lo mismo que las bibliotecas ineq de R Gini (x)

Chris
fuente
; CON t AS (SELECT CAST (ingreso 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) * SUM (x)) - 1.0- (1.0 / COUNT (x)) COMO gini FROM tt
Chris