I Stata 11 kan du med funktionen rowmedian beräkna radmedianer direkt med egen.
Hur beräknar jag radmedianer?
Titel | Beräkning av radmedianer | |
Författare | Nicholas J. Cox, Durham University |
Att beräkna medianer i statistiska programvaror som Stata borde vara enkelt, och det är det oftast. När man vill ha en radmedian – en median inom observationer över flera variabler av samma slag – verkar det knepigare.
Detta problem är värt en diskussion, inte bara för att det uppstår i praktiken. Det ger också ett litet exempel på olika delar av Stata i spel.
För att sammanfatta grunderna: Om du vill ha en median för en variabel kan du sortera på den variabeln och välja ut medianen själv. Det krävs viss försiktighet när du bara är intresserad av en del av observationerna eller när det finns saknade värden. Oftast startar användarna summarize, detail, som tar hand om alla sådana frågor, och identifierar medianen i resultaten. Den lämnas sedan i minnet omedelbart som r(p50).
Om du istället vill lägga in medianen i en variabel kan du använda egen, median(). Detta är mest meningsfullt när dina data är uppdelade i grupper och du vill att varje grupps median ska registreras för senare användning. Därför skulle du använda egen, median() tillsammans med by:.
När du har ett gäng variabler av samma slag finns det ibland ett enkelt svar. Om dessa variabler verkligen är paneldata eller longitudinella data bör du omforma long och arbeta med en annan datastruktur. Livet blir mycket enklare på det sättet, inte bara för radmedianer, som nu bara är panelmedianer, utan också för nästan alla typer av analyser du som kanske vill göra med sådana data.
Om du vet att värdena för dina radvariabler är i numerisk ordning, så att till exempel y1 alltid är mindre än eller lika med y2, som i sin tur är mindre än eller lika med y3, och så vidare, så kan medianen beräknas direkt som antingen en av variablerna eller som medelvärdet av två av variablerna, beroende på om antalet variabler är udda eller jämnt. Men det skulle bli rörigt av eventuella saknade värden.
Du kan komma till den situationen med radvariabler i numerisk ordning genom att använda rowsort från SSC (kräver Stata 8; fungerar endast med heltalsvärden) eller sortrows från SSC (kräver Stata 9).
Därefter kommer situationer när du har få variabler (två, tre eller fyra) som du vill ta radmedianen över – och återigen saknas inga värden. Medianen för två variabler är densamma som deras medelvärde, så det första fallet är enkelt:
. gen median = (y1 + y2) / 2
Ett mindre känt knep för tre variabler gör det också enkelt att lösa problemet:
. gen median = y1 + y2 + y3 - min(y1, y2, y3) - max(y1, y2, y3)
Med andra ord: räkna ut radsumman och subtrahera sedan minimum och maximum. Det som återstår måste vara medianen.
Nu är ett knep för fyra variabler omedelbart:
. gen median = (y1 + y2 + y3 + y4 - /// min(y1, y2, y3, y4) - max(y1, y2, y3, y4)) / 2
Med andra ord: räkna ut radsumman och subtrahera sedan minimum och maximum. Det som återstår är summan av de två inre värdena, och om man halverar den får man medianen.
Enkla knep för fem eller fler variabler finns i allmänhet inte.
En viss eftertanke visar att slipsar inte utgör något problem för något av dessa knep. Det mer besvärliga antagandet är att inga värden saknas. Det finns vissa möjligheter att rädda problem med saknade värden. Du kan beräkna antalet som saknas från
. egen nmissing = rowmiss(varlist)
men för ett fåtal variabler är det lika enkelt att räkna saknade variabler i farten.
Med alla saknade variabler kan medianen av två räddas genom
. gen median = (y1 + y2) / 2 . replace median = max(y1, y2) if median == .
Denna kommandosekvens utnyttjar det faktum att max(y1, y2) inte är saknad närhelst ett av värdena är det. Om båda värdena saknas förlorar vi inte riktigt, eftersom vissa missar bara skrivs över av missar. Du skulle kunna skriva min(y1, y2) om du känner dig mer bekväm med det. (Varför är resultatet detsamma?)
På samma sätt kan medianen av tre räddas.
. gen median = y1 + y2 + y3 - min(y1, y2, y3) - max(y1, y2, y3)
Om y1, y2 och y3 alla saknas har du redan det enda möjliga svaret: saknas. De situationer som måste åtgärdas är att bara en variabel saknas och att två variabler saknas i varje observation.
. replace median = max(y1, y2, y3) if (missing(y1) + missing(y2) + missing(y3)) == 2
Om två variabler saknas kan vi få fram den andra från max() och den är automatiskt medianen.
. 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
Om en variabel saknas ger medelvärdet av de andra två medianen. Vi ser till att missar ignoreras i summan genom att använda 0 i stället. Om vi visste att alla variabler ska vara positiva (eller noll) skulle man kunna använda termer som max(y1, 0) i stället för termer som cond(missing(y1), 0, y1), och om man visste att alla variabler ska vara negativa (eller noll) skulle man kunna använda min(y1, 0) i stället. Vidare skulle man kunna göra samma sak med egen:
. egen rowsum = rowsum(y1 y2 y3). replace median = rowsum / 2 ///if (missing(y1) + missing(y2) + missing(y3)) == 1
Uppenbarligen, även om koden hittills har ett visst kuriositetsvärde genom att visa att man inte alltid behöver sortera för att få fram radmedianer, behöver vi verkligen ett program som förkroppsligar ett mer systematiskt tillvägagångssätt.
Det finns dock ingen officiell egenfunktion för radmedianer. Om man letar efter funktioner som bidragits av gemenskapen och tittar noga på dem kan man börja förstå varför. I huvudsak var två tillvägagångssätt möjliga före Stata 9.
Det första, implementerat i egen, rmed() från STB-57 (Stata 5 krävs), är att slinga över observationer, kopiera värden till en variabel och sedan få fram medianen. Tyvärr förutsätter detta tillvägagångssätt att antalet berörda variabler inte är större än antalet observationer. Detta är vanligtvis men inte nödvändigtvis sant. Ännu viktigare är att detta tillvägagångssätt kan vara långsamt.
Det andra tillvägagångssättet, implementerat i egen, rmedf() från SSC (Stata 6 krävs), går ut på att omstrukturera datamängden i farten, beräkna medianer och sedan omstrukturera tillbaka. Man kan argumentera för att omstrukturering av ett dataset inte är något som bör göras mitt i en egen-funktion, men i vilket fall som helst kan detta tillvägagångssätt lätt misslyckas om inte tillräckligt med minne finns tillgängligt.
Med Stata 9 kommer dock en mer positiv möjlighet: att använda Mata. Paketet egenmore på SSC innehåller egen, rowmedian(). Den är mycket snabbare än tidigare egen-funktioner – även om den grundläggande slingan fortfarande är en slinga över observationer – och den kräver lite extra minne. Här är koden:
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