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 {
"m1202: " `lvl'
dis
}
levelsof m1202, loc(ausb)
`ausb'
glo ausb l ausb
mac
foreach lvl of global ausb {
"m1202: " `lvl'
dis
}
foreach lvl of global ausb {
"m1202: " `lvl'
dis 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'
list _len mac
_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' {
word: word `i' of `phrase1'
loc "this is word number " `i' ": `word'"
dis }
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 S1return 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 azereturn 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"Der Mittelwert beträgt: " r(mean) dis
Der Mittelwert beträgt: 1.496602
su S1"Der Mittelwert beträgt: " round(r(mean),.01) dis
Der Mittelwert beträgt: 1.5
foreach lvl of global ausb {
"m1202: " `lvl'
dis if m1202 == `lvl'
su S01 r(mean)
dis
}
foreach lvl of global ausb {
qui su S01 if m1202 == `lvl'
"Der Frauenanteil in m1202=" `lvl' " beträgt: " round(r(mean)*100,.1) "%"
dis
}
foreach lvl of global ausb {
qui su S01 if m1202 == `lvl'
`lvl': display "Der Frauenanteil in m1202=" `lvl' " beträgt: " round(r(mean)*100,.1) "%"
glo gend }
2.4.1 Rekursivität
Macros können auch “recursively” erstellt werden:
global x ""
forvalues i = 1/20 {
global x $x `i'
}list x mac
x: 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'
display "${gend}m1202=" `lvl' " " round(r(mean)*100,.1) "% "
glo gend:
}l gend mac
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
matrix
ausgeben:matrix list matname
eine
matrix
umbenennen:matrix umbenennen altername neuername
eine
matrix
oder alle löschen:matrix drop [matlist]
Operator | Symbol |
---|---|
column join | , |
row join | \\ |
transpose | ' |
negation | - |
matrix Y1 = 1, 3
l Y1 mat
Y1[1,2]
c1 c2
r1 1 3
matrix Y2 = 4\ 0
l Y2 mat
Y2[2,1]
c1
r1 4
r2 0
matrix Y = (2, 1.5 \ 2.5, 3)
l Y mat
Y[2,2]
c1 c2
r1 2 1.5
r2 2.5 3
Transponieren:
matrix X2 = (1, 2, 3 \ 5 , 8 , 9)
l X2
mat
mat X3 = X2'l X3 mat
X2[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:
J(4,2,0)
mat G0 = l G0 mat
G0[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 var2list G0 mat
G0[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:
year result
mat rowname G0 = list X1 mat
G0[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
`lvl' = `lvl' ,r(mean)*100
mat G
}
mat G = GX1\GX2\GX3\GX4
mat colname G = m1202 share_wl G mat
Damit 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
`lvl' = `lvl', r(p25), r(mean), r(p50), r(p75)
mat A
}
mat A = A1\A2\A3\A4mean median p75
mat colname A = m1202 p25 l A mat
A[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 m1202local vallab1 : label (`v') 1 // Value label für Wert = 1
"`vallab1'" // display local "valuelab1" dis
Ohne Berufsabschluss
In der Schleife können wir dann lvl
entsprechen für label (var) lvl
nutzen:
loc lvl = 1qui su zpalter if m1202 == `lvl', det
`lvl', r(p25), r(mean), r(p50), r(p75)
mat GX = local vallab1 : label (m1202) `lvl' // label aufrufen
2.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:
"label") mat M = c(2\
r(133);
end of do-file
r(133);
Aber wir können das Label als rowname ablegen:
loc lvl = 1qui su zpalter if m1202 == `lvl', det
`lvl', r(p25), r(mean), r(p50), r(p75)
mat GX = local vallab1 : label (m1202) `lvl' // label aufrufen
"`vallab1'" // in Zeilenname ablegen
mat rowname GX = l GX mat
…damit erweitern wir die Schleife von oben:
levelsof m1202, loc(ausb)
foreach lvl of local ausb {
qui su zpalter if m1202 == `lvl', det
`lvl' = `lvl', r(p25), r(mean), r(p50), r(p75)
mat GX
local vallab1 : label (m1202) `lvl'
`lvl' = "`vallab1'"
mat rowname GX
}
mat G = GX1\GX2\GX3\GX4mean median p75
mat colname G = m1202 p25 l G mat
1 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 xsvmat
rownames(lab)
xsvmat G, names(col) frame(res1)
frame change res1list, noobs clean
mean median p75
lab m1202 p25
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 nameX
können wir einen neuen Datensatz mit dem NamennameX
erstellen (der bisherige wird alsdefault
bezeichnet) - mit
frame dir
bekommen wir eine Übersicht zu den verschiedenenframe
s der aktuellen Stata-Session - mit
frame change
name können wir zwischen den verschiedenenframe
s hin- und herspringen
frame change res1default frame change
- mit
frame drop
name können wir einenframe
wieder löschen:
drop res1 frame
2.9 Übungen
2.9.1 Übung
- Zählen Sie die Wörter in den folgenden beiden String-locals
"ein sehr langer satz mit vielen wörtern"
loc x1
ds *wib*
x2 = r(varlist) loc
- Wie würde eine Schleife aussehen, die jeweils ein Wort aus den locals nacheinander mit
display
ausgibt?
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.su
odertabstat
zusammen mitreturn list
. - Erstellen Sie mit
display
eine 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 gkX
erstellt wird, wobeiX
für die Ausprägung vongkpol
steht und den entsprechenden Maximalwert vonF518_SUF
fü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
matrix
gesammelt werden.- Verwenden Sie den
row join
fürmatrix
mit,
um jeweils eine Ergebniszeile zu erstellen
- Verwenden Sie den
2.9.4 Übung
- Passen Ihre Schleife von eben mit
gkpol
so mit Hilfe der Schleife von oben so an, dass die Labels fürgkpol
alsrownames
werden legen Sie die Ergebnismatrix in einenframe
ab.- Nutzen Sie die
label (v') 1
extended macro function um das jeweilige Label anzuzeigen - Setzen Sie das entsprechende Label als
rowname
- Fügen Sie die einzelnen Ergebnis in eine
matrix
zusammen - Nutzen Sie
xsvmat
, um einenframe
zu erstellen - Nutzen Sie
frame change
, um in die Ergebnis-frame
zu wechseln (und wieder zurück)
- Nutzen Sie die