2 Schleifen aus Macros
2.1 local erstellen und für Schleifen verwenden
Schleifen aus globals / locals mit Hilfe von levelsof:
tab m1202
levelsof m1202
levelsof m1202, loc(ausb)
foreach lvl of local ausb {
dis "m1202: " `lvl'
}
levelsof m1202, loc(ausb)
glo ausb `ausb'
mac l ausb
foreach lvl of global ausb {
dis "m1202: " `lvl'
}
foreach lvl of global ausb {
dis "m1202: " `lvl'
tab S1 if m1202 == `lvl'
}2.2 Schleifen über strings
2.2.1 Wörter indizieren
local phrase `" "2 guys" "1 girl" "1 pizza place" "'
di "`:word 2 of `phrase' '"1 girl
2.2.2 Wörter zählen
local sentence "here is a sentence 7"
local len: word count `sentence'
mac list _len_len: 5
2.2.3 Wörter in Schleife
local phrase1 "here is a sentence of 7 words"
local len1: word count `phrase1'
forvalues i = 1(1)`len1' {
loc word: word `i' of `phrase1'
dis "this is word number " `i' ": `word'"
}this is word number 1: here
this is word number 2: is
this is word number 3: a
this is word number 4: sentence
this is word number 5: of
this is word number 6: 7
this is word number 7: words
… dabei macht es einen Unterschied, wo die "" stehen:
local phrase2 `" "here is" "a sentence" "of 7 words" "'
local len2: word count `phrase2'
forvalues i = 1(1)`len2' {
loc word: word `i' of `phrase2'
dis "this is word number " `i' ": `word'"
}this is word number 1: here is
this is word number 2: a sentence
this is word number 3: of 7 words
2.3 Informationen aus Schleifen behalten
2.3.1 Gespeicherte Ergebnisse
Um auf Ergebnisse zuzugreifen, können wir etwas hinter die Kulissen der Stata-Befehle sehen:
| Befehl | zeigt alle |
|---|---|
| c-class | system parameters & settings finden wir als `c()` |
| r-class | die meisten deskriptiven Befehle speichern die Ergebnisse in in `r()` |
| e-class | ...außer estimation commands, wie bspw. `reg` - hier wird in `e()` gespeichert (Postestimates) |
| s-class | parsing commands store results in `s()` used by programmers |
| n-class | commands that do not store in `r()`, `e()`, oder `s()` |
Jeweils alle Werte anzeigen mit:
| Befehl | zeigt alle |
|---|---|
| return list | r() |
| ereturn list | e() |
| sreturn list | s() |
| creturn list | c() |
Es gibt dabei vier Typen an Ergebnissen:
macro: strings mit mehreren Wörtern (Text)matrix: bspw.e(b)sind die Koeffizienten nach einemreg-Befehl odere(V)ist die Varianz–Kovarianz Matrix der estimates (VCE)scalar: einzelne Zahlen/Strings (1x1 Matrizen)functions: bspw.e(sample)\(\Rightarrow\) 1 (true) wenn die Beobachtung im vorheringen “estimation command” verwendet wurde und 0 (false) wenn nicht
tab S1
return list Geschlecht | Freq. Percent Cum.
------------+-----------------------------------
männlich | 10,074 50.34 50.34
weiblich | 9,938 49.66 100.00
------------+-----------------------------------
Total | 20,012 100.00
scalars:
r(N) = 20012
r(r) = 2
su S1
return list Variable | Obs Mean Std. Dev. Min Max
-------------+---------------------------------------------------------
S1 | 20,012 1.496602 .5000009 1 2
scalars:
r(N) = 20012
r(sum_w) = 20012
r(mean) = 1.496602038776734
r(Var) = .2500009464113147
r(sd) = .500000946410419
r(min) = 1
r(max) = 2
r(sum) = 29950
reg F518_SUF zpalter
ereturn list Source | SS df MS Number of obs = 16,543
-------------+---------------------------------- F(1, 16541) = 105.36
Model | 1.3092e+09 1 1.3092e+09 Prob > F = 0.0000
Residual | 2.0555e+11 16,541 12426773 R-squared = 0.0063
-------------+---------------------------------- Adj R-squared = 0.0063
Total | 2.0686e+11 16,542 12505168 Root MSE = 3525.2
------------------------------------------------------------------------------
F518_SUF | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
zpalter | 24.62253 2.398848 10.26 0.000 19.92053 29.32453
_cons | 2381.28 115.577 20.60 0.000 2154.736 2607.823
------------------------------------------------------------------------------
scalars:
e(N) = 16543
e(df_m) = 1
e(df_r) = 16541
e(F) = 105.3561454498825
e(r2) = .0063290815436915
e(rmse) = 3525.162828161657
e(mss) = 1309236899.97876
e(rss) = 205551251614.9366
e(r2_a) = .0062690083366028
e(ll) = -158590.4618746699
e(ll_0) = -158642.9792418738
e(rank) = 2
macros:
e(cmdline) : "regress F518_SUF zpalter"
e(title) : "Linear regression"
e(marginsok) : "XB default"
e(vce) : "ols"
e(depvar) : "F518_SUF"
e(cmd) : "regress"
e(properties) : "b V"
e(predict) : "regres_p"
e(model) : "ols"
e(estat_cmd) : "regress_estat"
matrices:
e(b) : 1 x 2
e(V) : 2 x 2
functions:
e(sample)
Anstatt zu versuchen, den Überblick darüber zu behalten, was wo gespeichert wird, finden wir ganz unten in jeder Hilfedatei einen Hinweis wie “summarize stores the following in r():” or “mean stores the following in e()” - entsprechend sehen wir die Ergebnisse in return bzw. ereturn.
2.3.2 e() und r() sind getrennte Welten
Neben dem Prinzip “One Data” folgt Stata auch dem Prinzip “One _-class”. Das bedeutet, dass wir nur den return oder ereturn für den letzten Befehl dieser Klasse sehen können. Wenn wir also reg ausführen und dann eine Reihe von r-Klassen-Aufrufen machen (z.B. su), wird uns der Aufruf von ereturn immer noch die Werte für reg anzeigen. Sobald wir jedoch einen weiteren r-class-Befehl ausführen, verlieren wir den Zugriff auf die Ergebnisse des ersten Befehls.
reg az F200
su az
ereturn list Source | SS df MS Number of obs = 17,376
-------------+---------------------------------- F(1, 17374) = 33637.44
Model | 1269310.92 1 1269310.92 Prob > F = 0.0000
Residual | 655608.985 17,374 37.735063 R-squared = 0.6594
-------------+---------------------------------- Adj R-squared = 0.6594
Total | 1924919.9 17,375 110.786757 Root MSE = 6.1429
------------------------------------------------------------------------------
az | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
F200 | .9897533 .0053965 183.41 0.000 .9791755 1.000331
_cons | 3.937849 .1903973 20.68 0.000 3.564651 4.311047
------------------------------------------------------------------------------
Variable | Obs Mean Std. Dev. Min Max
-------------+---------------------------------------------------------
az | 20,012 38.30557 11.75297 10 120
scalars:
e(N) = 17376
e(df_m) = 1
e(df_r) = 17374
e(F) = 33637.43995203968
e(r2) = .6594097320849045
e(rmse) = 6.142887188019294
e(mss) = 1269310.915908093
e(rss) = 655608.9846442067
e(r2_a) = .6593901286390708
e(ll) = -56197.03934279057
e(ll_0) = -65554.6676770772
e(rank) = 2
macros:
e(cmdline) : "regress az F200"
e(title) : "Linear regression"
e(marginsok) : "XB default"
e(vce) : "ols"
e(depvar) : "az"
e(cmd) : "regress"
e(properties) : "b V"
e(predict) : "regres_p"
e(model) : "ols"
e(estat_cmd) : "regress_estat"
matrices:
e(b) : 1 x 2
e(V) : 2 x 2
functions:
e(sample)
2.4 Ergebnisse weiter verwenden
Alle diese Informationen können wir mit einem Makro speichern bzw. weiter verarbeiten.
su S1
dis "Der Mittelwert beträgt: " r(mean)Der Mittelwert beträgt: 1.496602
su S1
dis "Der Mittelwert beträgt: " round(r(mean),.01)Der Mittelwert beträgt: 1.5
foreach lvl of global ausb {
dis "m1202: " `lvl'
su S01 if m1202 == `lvl'
dis r(mean)
}
foreach lvl of global ausb {
qui su S01 if m1202 == `lvl'
dis "Der Frauenanteil in m1202=" `lvl' " beträgt: " round(r(mean)*100,.1) "%"
}
foreach lvl of global ausb {
qui su S01 if m1202 == `lvl'
glo gend`lvl': display "Der Frauenanteil in m1202=" `lvl' " beträgt: " round(r(mean)*100,.1) "%"
}2.4.1 Rekursivität
Macros können auch “recursively” erstellt werden:
global x ""
forvalues i = 1/20 {
global x $x `i'
}
mac list xx: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
…somit können wir einen global auch zusammenbauen:
glo gend ""
foreach lvl of global ausb {
qui su S01 if m1202 == `lvl'
glo gend: display "${gend}m1202=" `lvl' " " round(r(mean)*100,.1) "% "
}
mac l gend 4. }
gend: m1202=1 45.6% m1202=2 53% m1202=3 37.8% m1202=4 48.9%
2.5 Kennzahlen in einer matrix ablegen
Matrizen helfen uns, die ergebnisse in handhabarer Form zu speichern (help matrix). Um eine Tabelle zu bauen benötigen wir einige Matrix-Befehle, weiteres unter help matrix operators
eine
matrixausgeben:matrix list matnameeine
matrixumbenennen:matrix umbenennen altername neuernameeine
matrixoder alle löschen:matrix drop [matlist]
| Operator | Symbol |
|---|---|
| column join | , |
| row join | \\ |
| transpose | ' |
| negation | - |
matrix Y1 = 1, 3
mat l Y1Y1[1,2]
c1 c2
r1 1 3
matrix Y2 = 4\ 0
mat l Y2Y2[2,1]
c1
r1 4
r2 0
matrix Y = (2, 1.5 \ 2.5, 3)
mat l YY[2,2]
c1 c2
r1 2 1.5
r2 2.5 3
Transponieren:
matrix X2 = (1, 2, 3 \ 5 , 8 , 9)
mat l X2
mat X3 = X2'
mat l X3X2[2,3]
c1 c2 c3
r1 1 2 3
r2 5 8 9
X3[3,2]
r1 r2
c1 1 5
c2 2 8
c3 3 9
Mit J(Zeilen,Spalten,Inhalt) können wir eine Matrix mit gleichen Werten besetzen:
mat G0 = J(4,2,0)
mat l G0G0[4,2]
c1 c2
r1 0 0
r2 0 0
r3 0 0
r4 0 0
2.5.1 Namen für Spalten und Zeilen einer matrix
Aber wir können die Zeilennamen einer matrix verändern:
mat colname G0 = var1 var2
mat list G0G0[4,2]
var1 var2
r1 0 0
r2 0 0
r3 0 2
r4 0 0
Wenn zu wenige Namen angegeben werden, wird der letzte Wert einfach wiederholt:
mat rowname G0 = year result
mat list X1G0[4,2]
c1 c2
year 0 0
result 0 0
result 0 2
result 0 0
2.5.2 matrix erstellen
Das nutzen wir jetzt um unsere Ergebnisse zu speichern:
levelsof m1202, loc(ausb)
foreach lvl of local ausb {
qui su S01 if m1202 == `lvl'
// 1. Spalte level von m1202
//2.Spalte: Frauenanteil
mat G`lvl' = `lvl' ,r(mean)*100
}
mat G = GX1\GX2\GX3\GX4
mat colname G = m1202 share_w
mat l GDamit können wir auch zeilenweise eine matrix befüllen, indem wir mit , mehrere Werte verbinden (row join):
qui levelsof m1202, loc(ausb)
foreach lvl of local ausb {
qui su zpalter if m1202 == `lvl', det
mat A`lvl' = `lvl', r(p25), r(mean), r(p50), r(p75)
}
mat A = A1\A2\A3\A4
mat colname A = m1202 p25 mean median p75
mat l AA[4,5]
m1202 p25 mean median p75
r1 1 29 42.627213 46 55
r1 2 39 47.076531 49 56
r1 3 41 48.092344 50 56
r1 4 39 47.760744 49 57
2.6 Labels behalten
2.6.1 extended macro function für Labels
Idealerweise würden wir aber gerne nicht nur 1-4 in m1202 behalten, sondern die Labels (Ohne Berufsabschluss) usw. Um Informationen zu Variablen & Labels abzurufen, lernen wir später eine ganze Reihe an extended macro functions kennen, für den Moment reicht uns label (varname) varvalue:
loc v m1202
local vallab1 : label (`v') 1 // Value label für Wert = 1
dis "`vallab1'" // display local "valuelab1"Ohne Berufsabschluss
In der Schleife können wir dann lvl entsprechen für label (var) lvl nutzen:
loc lvl = 1
qui su zpalter if m1202 == `lvl', det
mat GX = `lvl', r(p25), r(mean), r(p50), r(p75)
local vallab1 : label (m1202) `lvl' // label aufrufen2.6.2 Labels als rowname
Leider können wir nicht einfach die Labels der Variable in die matrix schreiben. In einer Matrix sind nur Zahlenwerte erlaubt:
mat M = c(2\"label")r(133);
end of do-file
r(133);
Aber wir können das Label als rowname ablegen:
loc lvl = 1
qui su zpalter if m1202 == `lvl', det
mat GX = `lvl', r(p25), r(mean), r(p50), r(p75)
local vallab1 : label (m1202) `lvl' // label aufrufen
mat rowname GX = "`vallab1'" // in Zeilenname ablegen
mat l GX…damit erweitern wir die Schleife von oben:
levelsof m1202, loc(ausb)
foreach lvl of local ausb {
qui su zpalter if m1202 == `lvl', det
mat GX`lvl' = `lvl', r(p25), r(mean), r(p50), r(p75)
local vallab1 : label (m1202) `lvl'
mat rowname GX`lvl' = "`vallab1'"
}
mat G = GX1\GX2\GX3\GX4
mat colname G = m1202 p25 mean median p75
mat l G1 2 3 4
G[4,5]
m1202 p25 mean median p75
Ohne Beruf~s 1 29 42.627213 46 55
duale o. s~l 2 39 47.076531 49 56
Aufstiegsf~T 3 41 48.092344 50 56
Fachhochsc~h 4 39 47.760744 49 57
2.7 Von der matrix zum Datensatz
Mit xsvmat bzw. dem ado xsvmat können wir eine matrix in einen Datensatz umwandeln. Mit rownames(lab) können wir Zeilennamen in die Variable lab ablegen. Außerdem nutzt xsvmat die neue frame- Funktion, um einen neuen Datensatz zu erstellen.
ssc install xsvmatxsvmat G, names(col) frame(res1) rownames(lab)
frame change res1
list, noobs clean lab m1202 p25 mean median p75
Ohne Berufsabschluss 1 29 42.62721 46 55
duale o. schulische Berufsausbildung/einf.,mittl. Beamte 2 39 47.07653 49 56
Aufstiegsfortbildung (Meister, Techniker, kfm. AFB u.ä.) 3 41 48.09234 50 56
Fachhochschule, Universität/ geh., höhere Beamte 4 39 47.76074 49 57 2.8 frame: mehrere Datensätze in Stata
Die frame-Option basiert auf einer relativ neuen Funktion in Stata. Seit Version 16 bietet Stata mit den frame-Befehlen auch die Möglichkeit, mehrere Datensätze parallel zu bearbeiten.
- mit
frame create nameXkönnen wir einen neuen Datensatz mit dem NamennameXerstellen (der bisherige wird alsdefaultbezeichnet) - mit
frame dirbekommen wir eine Übersicht zu den verschiedenenframes der aktuellen Stata-Session - mit
frame changename können wir zwischen den verschiedenenframes hin- und herspringen
frame change res1
frame change default- mit
frame dropname können wir einenframewieder löschen:
frame drop res12.9 Übungen
2.9.1 Übung
- Zählen Sie die Wörter in den folgenden beiden String-locals
loc x1 "ein sehr langer satz mit vielen wörtern"
ds *wib*
loc x2 = r(varlist)- Wie würde eine Schleife aussehen, die jeweils ein Wort aus den locals nacheinander mit
displayausgibt?
2.9.2 Übung
- Laden Sie die Erwerbstätigenbefragung - am besten in der Version ohne Missings in den relevanten Variablen (
"${data}/BIBBBAuA_2018_suf1.0_clean.dta", siehe01_init.do) - Erstellen Sie eine Schleife, welche jeweils das Maximaleinkommen (basierend auf
F518_SUF) für die Gemeindegrößenklassen (gkpol) anzeigt.- Wie kommen Sie an den Maximalwert für
F518_SUF? Verwenden Sie bspw.suodertabstatzusammen mitreturn list. - Erstellen Sie mit
displayeine aussagekräftige Ausgabe - Testen Sie Ihre Schleifenlogik mit einem
local, um anschließend die Schleife “außen herumzubauen” - Welche Ausprägungen hat
gkpol- wie können Sie diese automatisch in eine Schleife überführen?
- Wie kommen Sie an den Maximalwert für
- Optional Passen Sie Ihre Schleife an, sodass für jeden Durchlauf ein
global gkXerstellt wird, wobeiXfür die Ausprägung vongkpolsteht und den entsprechenden Maximalwert vonF518_SUFfür die entsprechende Größenklasse enthält.
2.9.3 Übung
- Kopieren Sie die in Übung 2 erstellte Schleife und passen Sie diese so an, dass jeweils die Werte für Min, Mean, Median, Max und N in
matrixgesammelt werden.- Verwenden Sie den
row joinfürmatrixmit,um jeweils eine Ergebniszeile zu erstellen
- Verwenden Sie den
2.9.4 Übung
- Passen Ihre Schleife von eben mit
gkpolso mit Hilfe der Schleife von oben so an, dass die Labels fürgkpolalsrownameswerden legen Sie die Ergebnismatrix in einenframeab.- Nutzen Sie die
label (v') 1extended macro function um das jeweilige Label anzuzeigen - Setzen Sie das entsprechende Label als
rowname - Fügen Sie die einzelnen Ergebnis in eine
matrixzusammen - Nutzen Sie
xsvmat, um einenframezu erstellen - Nutzen Sie
frame change, um in die Ergebnis-framezu wechseln (und wieder zurück)
- Nutzen Sie die