3  Regressionsergebnisse weiterverarbeiten

3.1 e() und r() der Regressionsergebnisse

Die Koeffizienten und Standardfehler des letzten Modells werden in e() gespeichert:

reg F518_SUF F200
      Source |       SS           df       MS      Number of obs   =    14,659
-------------+----------------------------------   F(1, 14657)     =   1370.76
       Model |  1.3122e+10         1  1.3122e+10   Prob > F        =    0.0000
    Residual |  1.4031e+11    14,657  9572601.57   R-squared       =    0.0855
-------------+----------------------------------   Adj R-squared   =    0.0855
       Total |  1.5343e+11    14,658  10467142.3   Root MSE        =      3094

------------------------------------------------------------------------------
    F518_SUF |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
        F200 |   109.4473   2.956134    37.02   0.000     103.6529    115.2417
       _cons |  -344.1221   104.2802    -3.30   0.001    -548.5245   -139.7197
------------------------------------------------------------------------------
mat l e(b)
e(b)[1,2]
          F200       _cons
y1   109.44727  -344.12212

3.1.1 Koeffizienten mit _b / _se aufrufen

Allerdings gibt es noch eine Abkürzung mit _b[varname] bzw. _se[varname]:

dis "Der Koeffizient für F200 ist " _b[F200]
dis "Der Standardfehler des Koeffizienten für F200 ist " _se[F200]
Der Koeffizient für F200 ist 109.44727

Der Standardfehler des Koeffizienten für F200 ist 2.9561335

Wir können so auch vorhergesagte Werte berechnen - entweder für spezifische Werte:

dis _b[_cons] + 20 *_b[F200]
margins, at(F200 = 20)
1844.8234


Adjusted predictions                            Number of obs     =     14,659
Model VCE    : OLS

Expression   : Linear prediction, predict()

------------------------------------------------------------------------------
             |            Delta-method
             |     Margin   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
       _cons |   1844.823   49.14441    37.54   0.000     1748.494    1941.153
------------------------------------------------------------------------------

…oder für alle Beobachtungen:

gen pred_manual = _b[_cons] + F200 *_b[F200]
predict pred_auto, xb
gen diff=  pred_manual - pred_auto
su diff
    Variable |        Obs        Mean    Std. Dev.       Min        Max
-------------+---------------------------------------------------------
        diff |     17,376           0           0          0          0

3.1.2 Komplette Regressionstabelle

Die vollständige Regressionstabelle ist aber eine r-Class matrix:

reg F518_SUF F200
matlist r(table) 
r(table)[9,2]
              F200       _cons
     b   109.44727  -344.12212
    se   2.9561335   104.28024
     t   37.023793  -3.2999743
pvalue   6.36e-287   .00096924
    ll   103.65288  -548.52452
    ul   115.24167  -139.71973
    df       14657       14657
  crit   1.9601259   1.9601259
 eform           0           0

3.2 Regressionstabellen als matrix speichern und anpassen

Mit ' können wir die Regressionstabelle transponieren:

reg F518_SUF F200
mat C = r(table)'
mat l C
C[2,9]
                b          se           t      pvalue          ll          ul
 F200   109.44727   2.9561335   37.023793   6.36e-287   103.65288   115.24167
_cons  -344.12212   104.28024  -3.2999743   .00096924  -548.52452  -139.71973

               df        crit       eform
 F200       14657   1.9601259           0
_cons       14657   1.9601259           0

rownumb hilft, einen Koeffizienten zu suchen:

mat C1 = C[rownumb(C,"F200"),1...]
mat l C1
C1[1,9]
              b         se          t     pvalue         ll         ul
F200  109.44727  2.9561335  37.023793  6.36e-287  103.65288  115.24167

             df       crit      eform
F200      14657  1.9601259          0

3.3 kategoriale UV

Der Koeffizientenname ist etwas komplizierterer Name bei kat. UVs:

reg F518_SUF i.S1 F200
ereturn list
mat l r(table) 
dis "Der Koeffizient für S1 = weiblich ist " _b[2.S1]
r(table)[9,4]
                1b.          2.                        
                S1          S1        F200       _cons
     b           0  -628.91281    95.08006   464.42184
    se           .   55.392637   3.2038116   125.90363
     t           .  -11.353726    29.67717    3.688709
pvalue           .   9.461e-30   5.23e-188   .00022621
    ll           .  -737.48935   88.800186   217.63489
    ul           .  -520.33627   101.35993    711.2088
    df       14656       14656       14656       14656
  crit   1.9601259   1.9601259   1.9601259   1.9601259
 eform           0           0           0           0

Der Koeffizient für S1 = weiblich ist -628.91281

Dies müssen wir auch bei der Suche nach einem Koeffizienten berücksichtigen:

mat D = r(table)' // transponieren:
mat l D
                b          se           t      pvalue          ll          ul          df        crit       eform
1b.S1           0           .           .           .           .           .       14656   1.9601259           0
 2.S1  -628.91281   55.392637  -11.353726   9.461e-30  -737.48935  -520.33627       14656   1.9601259           0
 F200    95.08006   3.2038116    29.67717   5.23e-188   88.800186   101.35993       14656   1.9601259           0
_cons   464.42184   125.90363    3.688709   .00022621   217.63489    711.2088       14656   1.9601259           0

3.4 Als Datensatz ablegen:

Auch hier können wir dann mit xsvmat die Matrix in einen Datensatz umformatieren:

cap frame drop regres1
xsvmat D,  names(col) rownames(coef) frame(regres1)
frame change regres1

list, noobs clean
 coef           b         se           t     pvalue          ll          ul      df       crit   eform  
1b.S1           0          .           .          .           .           .   14656   1.960126       0  
 2.S1   -628.9128   55.39264   -11.35373   9.46e-30   -737.4893   -520.3362   14656   1.960126       0  
 F200    95.08006   3.203812    29.67717          0    88.80019    101.3599   14656   1.960126       0  
_cons    464.4218   125.9036    3.688709   .0002262    217.6349    711.2088   14656   1.960126       0  

3.5 weitere Infos aus e()

In ereturn list oben sehen wir, dass e(cmdline) den reg-Befehl enthält:

 reg F518_SUF i.S1 F200
dis "`e(cmdline)'"
regress F518_SUF i.S1 F200

Diese Information können wir mit in den Ergebnis-frame nehmen. globals bleiben nehmen in der Session erhalten, auch wenn wir zwischen frames wechseln:

gen mo = "`e(cmdline)'"
list, noobs clean
 coef           b         se           t     pvalue          ll          ul      df       crit   eform                           mo  
1b.S1           0          .           .          .           .           .   14656   1.960126       0   regress F518_SUF i.S1 F200  
 2.S1   -628.9128   55.39264   -11.35373   9.46e-30   -737.4893   -520.3362   14656   1.960126       0   regress F518_SUF i.S1 F200  
 F200    95.08006   3.203812    29.67717          0    88.80019    101.3599   14656   1.960126       0   regress F518_SUF i.S1 F200  
_cons    464.4218   125.9036    3.688709   .0002262    217.6349    711.2088   14656   1.960126       0   regress F518_SUF i.S1 F200  

Diese Beschreibung ist natürlich alles andere als ideal. Im nächsten Kapitel werden wir einige Möglichkeiten kennenlernen, da etwas zu ändern.


Übung


3.5.1 e(sample)

e(sample) ist eine e()-Class Funktion, welche die in einem Modell berücksichtigten Fälle zu markieren:

quietly reg F518_SUF i.S1 F200
gen smpl = e(sample)
tab sampl
       smpl |      Freq.     Percent        Cum.
------------+-----------------------------------
          0 |      5,353       26.75       26.75
          1 |     14,659       73.25      100.00
------------+-----------------------------------
      Total |     20,012      100.00

So können wir bspw. sehen, wo die Missings liegen:

mdesc  F518_SUF S1 F200 if smpl == 0
quietly{
  use "./data/BIBBBAuA_2018_suf1.0_clean.dta", replace 
  reg F518_SUF i.S1 F200
  gen smpl = e(sample)
}
mdesc  F518_SUF S1 F200 if smpl == 0
    Variable    |     Missing          Total     Percent Missing
----------------+-----------------------------------------------
       F518_SUF |       3,377          5,353          63.09
             S1 |           0          5,353           0.00
           F200 |       2,636          5,353          49.24
----------------+-----------------------------------------------

3.6 reg schrittweise aufbauen

glo mod1 i.S1 az i.m1202 zpalter i.Mig
qui regress F518_SUF ${mod1}
gen smpl2 = e(sample)

local len2: word count ${mod1}
forvalues i = 1(1)`len2' {
    loc word: word `i' of ${mod1}
    dis "Modell Nr" `i' ": mit `word'"
    loc x `x' `word'
    qui reg F518_SUF `x' if smpl2 == 1
    est store m`i'
}

est dir
esttab m*, b se  // ssc install esttab
Modell Nr1: mit i.S1
Modell Nr2: mit az
Modell Nr3: mit i.m1202
Modell Nr4: mit zpalter
Modell Nr5: mit i.Mig


----------------------------------------------------------------
        name | command      depvar       npar  title 
-------------+--------------------------------------------------
          m1 | regress      F518_SUF        3  Linear regression
          m2 | regress      F518_SUF        4  Linear regression
          m3 | regress      F518_SUF        8  Linear regression
          m4 | regress      F518_SUF        9  Linear regression
          m5 | regress      F518_SUF       12  Linear regression
----------------------------------------------------------------


--------------------------------------------------------------------------------------------
                      (1)             (2)             (3)             (4)             (5)   
                 F518_SUF        F518_SUF        F518_SUF        F518_SUF        F518_SUF   
--------------------------------------------------------------------------------------------
1.S1                    0               0               0               0               0   
                      (.)             (.)             (.)             (.)             (.)   

2.S1              -1434.1***       -683.3***       -725.7***       -755.7***       -756.4***
                  (53.94)         (55.19)         (53.65)         (53.50)         (53.51)   

az                                  91.74***        83.46***        84.05***        83.99***
                                  (2.376)         (2.323)         (2.315)         (2.316)   

1.m1202                                                 0               0               0   
                                                      (.)             (.)             (.)   

2.m1202                                             384.1***        261.9*          250.9*  
                                                  (114.5)         (114.6)         (115.2)   

3.m1202                                             898.1***        737.2***        724.5***
                                                  (137.7)         (137.9)         (138.5)   

4.m1202                                            2074.7***       1933.3***       1924.7***
                                                  (116.0)         (116.2)         (116.7)   

zpalter                                                             25.41***        25.27***
                                                                  (2.200)         (2.210)   

0.Mig                                                                                   0   
                                                                                      (.)   

1.Mig                                                                               10.65   
                                                                                  (93.55)   

2.Mig                                                                              -175.8   
                                                                                  (146.9)   

_cons              4236.3***        359.5***       -376.7**       -1447.4***      -1423.9***
                  (37.72)         (106.7)         (141.0)         (168.3)         (171.2)   
--------------------------------------------------------------------------------------------
N                   16518           16518           16518           16518           16518   
--------------------------------------------------------------------------------------------
Standard errors in parentheses
* p<0.05, ** p<0.01, *** p<0.001

Übung


3.7 Übungen

3.7.1 Übung

Erstellen Sie folgendes Regressionsmodell:

reg az i.mig01 zpalter

(In mig01 steht dann 0 für keinen Migrationshintergrund und 1 für Migrationshintergrund - siehe auch 01_init.do)

  • Erstellen Sie jeweils einen display-Befehl, der den Koeffizienten und Standardfehler für mig01 und zpalter mit einer Aussagekräftigen Nachricht ausgibt
  • Wie würde das als Schleife über die Koeffizienten aussehen?
  • Extrahieren Sie die Regressionstabelle als matrix und legen sie diese als frame ab.
  • Erstellen Sie zusätzlich eine Spalte mit dem Regressionsbefehl.

3.7.2 Übung

Bauen Sie folgendes Modell Schritt für Schritt auf und lassen Sie sich die Tabelle mit esttab ausgeben:

reg az i.S1 zpalter c.zpalter#c.zpalter i.gkpol i.F1604 i.F1604##i.S1

3.8 Anhang

3.8.1 statsby

statsby _b _se, by(Bula) noisily: ///
    regress F518_SUF c.F200##c.F200 i.m1202 i.S1

3.8.2 reg-Ergebnisse für Modelle sammeln: Schleife

Wir können mit den matrix-Befehlen auch eine Schleife bauen, welche eine Reihe an Regressionsmodellen schätzt und bei jedem Durchlauf einen zusätzlichen Term hinzunimmt. Wir interessieren uns aber nur, dafür wie sich der Koeffizient für das Geschlecht (S1 == 2) entwickelt mit jedem neuen Modell. Mit den matrix-Befehlen können wir dieser herausfiltern.

local predictors i.S1 c.F200 c.F200#c.F200 i.m1202 zpalter c.zpalter#c.zpalter // UV-Liste
local r = 1 // Zähler 
loc uv      // uv rücksetzen (zur sicherheit)
foreach v of local predictors {
  local uv `uv' `v'
    qui regress F518_SUF `uv'
    mat D = r(table)'                       // reg-tabelle transponieren & speichern 
    mat D2 = D[rownumb(D,"2.S1"),1...]      // Koeffizient für S1=2 behalten
    
    if (`r' == 1) mat R = D2                // im ersten Durchlauf R erstellen
    if (`r' != 1) mat R = R\D2              // danach: D2 an R anfügen
        
    loc ++r // Zähler + 1
}
mat l R
R[6,9]
               b          se           t      pvalue          ll          ul          df        crit       eform
2.S1  -1431.8093   53.630001  -26.697917   8.52e-154  -1536.9298  -1326.6888       16633   1.9601066           0
2.S1  -628.91281   55.392637  -11.353726   9.461e-30  -737.48935  -520.33627       14656   1.9601259           0
2.S1   -661.6656   55.679749  -11.883416   2.034e-32  -770.80492  -552.52628       14655   1.9601259           0
2.S1  -664.94219   53.793012  -12.361126   6.336e-35  -770.38328  -559.50111       14633   1.9601261           0
2.S1  -700.71303   54.028438  -12.969337   2.975e-38  -806.61563  -594.81043       14552    1.960127           0
2.S1  -717.33567   54.061055  -13.268991   5.977e-40  -823.30221  -611.36914       14551    1.960127           0

Wie wissen wir jetzt, für was kontrolliert wurde?

Wir nutzen den Zähler, um ein global mit der Zählernummer zu erstellen und eine Zeile in die matrix einzufügen:

local predictors i.S1 c.F200 c.F200#c.F200 i.m1202 zpalter c.zpalter#c.zpalter
local r = 1 // Zähler 
loc uv      // uv rücksetzen (zur sicherheit)
foreach v of local predictors {
    local uv `uv' `v'
    qui regress F518_SUF `uv'
    mat D = r(table)'                       // reg-tabelle transponieren & speichern 
    mat D2 = D[rownumb(D,"2.S1"),1...]      // Koeffizient für S1=2 behalten
    
    mat M = `r'
    mat colname M = mod
    
    if (`r' == 1) mat R = D2 , M            // ,r -> zähler an Koeffizientzeile anfügen
    if (`r' != 1) mat R = R\(D2 , M)
    glo cmd`r' = "`e(cmdline)'"
    loc ++r // Zähler + 1
}
mat l R
R[6,10]
               b          se           t      pvalue          ll          ul          df        crit       eform         mod
2.S1  -1431.8093   53.630001  -26.697917   8.52e-154  -1536.9298  -1326.6888       16633   1.9601066           0           1
2.S1  -628.91281   55.392637  -11.353726   9.461e-30  -737.48935  -520.33627       14656   1.9601259           0           2
2.S1   -661.6656   55.679749  -11.883416   2.034e-32  -770.80492  -552.52628       14655   1.9601259           0           3
2.S1  -664.94219   53.793012  -12.361126   6.336e-35  -770.38328  -559.50111       14633   1.9601261           0           4
2.S1  -700.71303   54.028438  -12.969337   2.975e-38  -806.61563  -594.81043       14552    1.960127           0           5
2.S1  -717.33567   54.061055  -13.268991   5.977e-40  -823.30221  -611.36914       14551    1.960127           0           6

Diese matrix R schicken wir jetzt in einen frame:

cap frame drop rmods
xsvmat R,  names(col) rownames(coef) frame(rmods)
frame change rmods

list, noobs clean
coef           b         se           t     pvalue          ll          ul      df       crit   eform   mod  
2.S1   -1431.809      53.63   -26.69792          0    -1536.93   -1326.689   16633   1.960107       0     1  
2.S1   -628.9128   55.39264   -11.35373   9.46e-30   -737.4893   -520.3362   14656   1.960126       0     2  
2.S1   -661.6656   55.67975   -11.88342   2.03e-32   -770.8049   -552.5263   14655   1.960126       0     3  
2.S1   -664.9422   53.79301   -12.36113   6.34e-35   -770.3833   -559.5011   14633   1.960126       0     4  
2.S1    -700.713   54.02844   -12.96934   2.97e-38   -806.6156   -594.8104   14552   1.960127       0     5  
2.S1   -717.3357   54.06105   -13.26899          0   -823.3022   -611.3691   14551   1.960127       0     6  

Jetzt wissen zwar schon mal, aus welchem Modell der Koeffizient jeweils kommt (basierend auf mod). Eigentlich würden das aber gerne labeln. Dazu können wir jetzt auf die globals zurückgreifen - mit all globals können wir nach ihnen suchen:

global allglo:  all globals "cmd*"
mac l allglo
allglo:         cmd6 cmd5 cmd4 cmd3 cmd2 cmd1
mac l cmd1
cmd1:           regress F518_SUF i.S1

Jetzt können wir mit einer Schleife die Spalte mod labeln. Mit label define .... können Wertelabels erstellt werden - mit der Option ,modify können wir das auch schrittweise verändern. Außerdem können wir einen kleinen Trick nutzen, um innerhalb der Schleife auf das global mit einer bestimmten Zahl zuzugreifen:

levelsof mod, loc(mnrs)
  foreach m of local mnrs {
    lab def mod_lab `m' "${cmd`m'}", modify // value label verändern 
  }
lab val mod mod_lab

list, noobs clean
    coef           b         se           t     pvalue          ll          ul      df       crit   eform                                                                              mod  
    2.S1   -1431.809      53.63   -26.69792          0    -1536.93   -1326.689   16633   1.960107       0                                                            regress F518_SUF i.S1  
    2.S1   -628.9128   55.39264   -11.35373   9.46e-30   -737.4893   -520.3362   14656   1.960126       0                                                     regress F518_SUF i.S1 c.F200  
    2.S1   -661.6656   55.67975   -11.88342   2.03e-32   -770.8049   -552.5263   14655   1.960126       0                                       regress F518_SUF i.S1 c.F200 c.F200#c.F200  
    2.S1   -664.9422   53.79301   -12.36113   6.34e-35   -770.3833   -559.5011   14633   1.960126       0                               regress F518_SUF i.S1 c.F200 c.F200#c.F200 i.m1202  
    2.S1    -700.713   54.02844   -12.96934   2.97e-38   -806.6156   -594.8104   14552   1.960127       0                       regress F518_SUF i.S1 c.F200 c.F200#c.F200 i.m1202 zpalter  
    2.S1   -717.3357   54.06105   -13.26899          0   -823.3022   -611.3691   14551   1.960127       0   regress F518_SUF i.S1 c.F200 c.F200#c.F200 i.m1202 zpalter c.zpalter#c.zpalter  

Daraus können wir beispielsweise einen Koeffizientenplot erstellen:

graph twoway ///
    (rcap ll ul mod,horizontal lcolor("57 65 101") ) /// Konfidenzintervalle
    (scatter mod b,  mcolor("177 147 74") )  , /// Punktschätzer
    graphregion(fcolor(white)) /// Hintergundfarbe (außerhalb des eigentlichen Plots)
    ylabel(, valuelabel angle(0) labsize(tiny)) ///
    legend(off) ///
    xtitle("Einkommen (W) vs. Einkommen (M)") /// Achsentitel
    ytitle("") /// 
    title("Titel")  ///
    subtitle("Untertitel") ///
    caption("{it:Quelle: Erwerbstätigenbefragung 2018}", size(8pt) position(5) ring(5) )

Diese labels sind natürlich alles andere als ideal. Im nächsten Kapitel werden wir einige Möglichkeiten kennenlernen, da etwas zu ändern.