In Stata 11, la funzione rowmedian ti permette di calcolare le mediane di riga direttamente con egen.
Come si calcolano le mediane di riga?
Titolo | Calcolo delle mediane di riga | |
Autore | Nicholas J. Cox, Durham University |
Il calcolo delle mediane in software statistici come Stata dovrebbe essere facile, e di solito lo è. Quando si vuole una mediana di riga – una mediana all’interno delle osservazioni di diverse variabili dello stesso tipo – appare più complicato.
Questo problema merita una discussione, non solo perché si presenta nella pratica. Fornisce anche un piccolo esempio di varie parti di Stata in gioco.
Per ricapitolare le basi: se volete una mediana di una variabile, potete ordinare su quella variabile e scegliere la mediana da soli. Un po’ di attenzione è necessaria quando si è interessati solo ad alcune delle osservazioni o ci sono valori mancanti. Per lo più, gli utenti avviano summarize, detail, che si occupa di tutte queste questioni, e identificano la mediana all’interno dei risultati. Viene poi lasciata immediatamente in memoria come r(p50).
Se invece volete mettere la mediana in una variabile, potete usare egen, median(). Questo ha più senso quando i vostri dati sono suddivisi in gruppi e volete che ogni mediana di gruppo sia registrata per un uso successivo. Quindi usereste egen, median() insieme a by:.
Quando avete un mucchio di variabili dello stesso tipo, a volte c’è una risposta facile. Se quelle variabili sono davvero dati panel o longitudinali, dovreste rimodellare il lungo e lavorare con una diversa struttura dei dati. La vita sarà molto più facile in questo modo, non solo per le mediane di riga, che ora sono solo mediane di pannello, ma anche per quasi tutti i tipi di analisi che potreste voler fare con tali dati.
Se sapete che i valori delle vostre variabili di riga sono in ordine numerico, così che per esempio y1 è sempre minore o uguale a y2, che a sua volta è minore o uguale a y3, e così via, allora la mediana può essere calcolata direttamente come una delle variabili o la media di due delle variabili, a seconda che il numero di variabili sia pari o dispari. Ma questo sarebbe incasinato da qualsiasi valore mancante.
Si può arrivare a quella situazione di variabili di riga in ordine numerico usando rowsort da SSC (richiede Stata 8; funziona solo con valori interi) o sortrows da SSC (richiede Stata 9).
Seguono situazioni in cui si hanno poche variabili (due, tre o quattro) su cui si vuole prendere la mediana di riga – e di nuovo nessun valore manca. La mediana di due variabili è uguale alla loro media, quindi il primo caso è facile:
. gen median = (y1 + y2) / 2
Un trucco meno noto per tre variabili rende anche la soluzione del problema semplice:
. gen median = y1 + y2 + y3 - min(y1, y2, y3) - max(y1, y2, y3)
In parole povere: calcola la somma delle righe; poi sottrai il minimo e il massimo. Ciò che rimane deve essere la mediana.
Ora un trucco per quattro variabili è immediato:
. gen median = (y1 + y2 + y3 + y4 - /// min(y1, y2, y3, y4) - max(y1, y2, y3, y4)) / 2
In parole povere: calcola la somma delle righe; poi sottrai il minimo e il massimo. Ciò che rimane è la somma dei due valori interni, e dimezzando si ottiene la mediana.
I trucchi semplici per cinque o più variabili, in generale, non sono in evidenza.
Un po’ di riflessione mostra che i pareggi non pongono problemi a nessuno di questi trucchi. L’ipotesi più scomoda è che non manchino valori. C’è qualche possibilità di salvare i problemi con i valori mancanti. Potete calcolare il numero di valori mancanti da
. egen nmissing = rowmiss(varlist)
ma per poche variabili, contare le variabili mancanti al volo è altrettanto facile.
Con qualsiasi variabile mancante, la mediana di due può essere recuperata da
. gen median = (y1 + y2) / 2 . replace median = max(y1, y2) if median == .
Questa sequenza di comandi sfrutta il fatto che max(y1, y2) è non mancante quando uno dei valori lo è. Se entrambi i valori sono mancanti, non ci perdiamo veramente, poiché alcune mancanze sono semplicemente sovrascritte da altre mancanze. Potreste scrivere min(y1, y2) se questo vi facesse sentire più a vostro agio. (Perché il risultato è lo stesso?)
Allo stesso modo, la mediana di tre può essere recuperata.
. gen median = y1 + y2 + y3 - min(y1, y2, y3) - max(y1, y2, y3)
Se y1, y2 e y3 sono tutti mancanti, avete già l’unica risposta possibile: mancante. Le situazioni da risolvere sono che manchi una sola variabile e che manchino due variabili in ogni osservazione.
. replace median = max(y1, y2, y3) if (missing(y1) + missing(y2) + missing(y3)) == 2
Se mancano due variabili, allora possiamo ottenere l’altra da max() ed è automaticamente la mediana.
. replace median = ( /// cond(missing(y1), 0, y1) + /// cond(missing(y2), 0, y2) + /// cond(missing(y3), 0, y3) ) / 2 /// if (missing(y1) + missing(y2) + missing(y3)) == 1
Se manca una variabile, allora la media delle altre due dà la mediana. Ci assicuriamo che le mancanze siano ignorate nella somma usando invece 0. Se sapessimo che tutte le variabili dovrebbero essere positive (o zero), allora potreste usare termini come max(y1, 0) piuttosto che termini come cond(missing(y1), 0, y1), e se sapeste che tutte le variabili dovrebbero essere negative (o zero), potreste usare invece min(y1, 0). Inoltre, potreste fare la stessa cosa con egen:
. egen rowsum = rowsum(y1 y2 y3). replace median = rowsum / 2 ///if (missing(y1) + missing(y2) + missing(y3)) == 1
Manifestamente, anche se il codice finora ha un certo valore di curiosità nel mostrare che non è sempre necessario ordinare per ottenere le mediane di riga, abbiamo davvero bisogno di un programma che incarni un approccio più sistematico.
Tuttavia, non esiste una funzione egen ufficiale per le mediane di riga. Se cercate le funzioni fornite dalla comunità e le guardate attentamente, potete iniziare a capire perché. In sostanza, due approcci erano possibili prima di Stata 9.
Il primo, implementato in egen, rmed() da STB-57 (Stata 5 richiesto), è quello di fare un loop sulle osservazioni, copiare i valori in una variabile e poi ottenere la mediana. Purtroppo, questo approccio presuppone che il numero di variabili interessate non sia maggiore del numero di osservazioni. Questo di solito è vero, ma non necessariamente. Ancora più importante, questo approccio può essere davvero lento.
Il secondo, implementato in egen, rmedf() da SSC (Stata 6 richiesto), è quello di ristrutturare il dataset al volo, calcolare le mediane, e poi ristrutturare di nuovo. Probabilmente, ristrutturare un dataset non è qualcosa che dovrebbe essere fatto nel mezzo di una funzione egen, ma in ogni caso questo approccio potrebbe facilmente fallire se non fosse disponibile abbastanza memoria.
Con Stata 9, tuttavia, arriva un’opportunità più positiva: usare Mata. Il pacchetto egenmore su SSC include egen, rowmedian(). È molto più veloce delle precedenti funzioni egen – anche se il ciclo di base è ancora un ciclo sulle osservazioni – e richiede poca memoria extra. Ecco il codice:
program _growmedian version 9 gettoken type 0 : 0 gettoken h 0 : 0 gettoken eqs 0 : 0 syntax varlist(numeric) if `"`by'"' != "" { _egennoby rowmedian() `"`by'"' /* NOTREACHED */ } marksample touse, novarlist quietly { mata : row_median("`varlist'", "`touse'", "`h'", "`type'") } end mata : void row_median(string scalar varnames, string scalar tousename, string scalar medianname, string scalar type) { real matrix y real colvector median, row real scalar n st_view(y, ., tokens(varnames), tousename) median = J(rows(y), 1, .) for(i = 1; i