// Open Allbus 1980-2016:
use id03 eastwest year using "allbus\ZA4586_v1-0-0.dta", clear
recode id03 (-1 -7 -8 -9 -13 = .), gen(topbot)
recode eastwest (2 = 1) (1 = 0), gen(east)
table year, c(mean topbot)
collapse topbot, by(year east)
twoway (scatter topbot year if east == 0, connect(L)) ///
(scatter topbot year if east == 1, connect(L)) ///
, ylabel(4 (.5) 7, format(%6.1f)) ///
xlabel(1980 1982 1986 1988 1990 1991 1992 2000 (2) 2016, alt) ///
xtitle("Survey year") ///
ytitle("Average ladder ranking") ///
legend(order(1 "West Germany" 2 "East Germany") pos(11) ring(0)) ///
note("{it: Source:} German General Social Survey 1980-2016, doi:10.4232/1.13029", justification(left) bexpand span)
Showing posts with label Allbus. Show all posts
Showing posts with label Allbus. Show all posts
Feb 27, 2020
Random graphs (143): Scatterplot
Labels:
Allbus,
Random graphs,
twoway line
Oct 26, 2019
Inverse probability of treatment weighting
// Allbus 2018
use xr19 sex age isced97 eastwest german pt09 pt10 wghtpew bik using "ZA5272_v1-0-0.dta", clear
// Outcome: Trust in media
recode pt09 pt10 (-9 = .)
alpha pt09 pt10
scores trust = mean(pt09 pt10), nv(1)
label var trust "Trust in media"
drop pt09 pt10
// Treatment: Internet use
gen internet = (xr19 == 1) if !inlist(xr19, -9, -8)
label define internet 1 "Internet user" 0 "Internet non-user"
label val internet internet
drop xr19
// Gender
gen female = (sex == 2)
label var female "Female sex"
drop sex
// Age
recode age (-32 = .)
label var age "Age"
// Education
recode isced97 (-32 = .)
label define isced97 1 "Basic" 2 "Lower secondary" 3 "Upper secondary" 4 "Post-secondary" 5 "Tertiary first" 6 "Tertiary second", modify
label var isced97 "Education"
// East
generate east = (eastwest == 2)
label var east "Eastern Germany"
drop eastwest
// German
recode german (1 = 0) (2 = 0) (3 = 1) (-50 = 1), gen(foreign)
label var foreign "Foreign citizen"
drop german
// Region
recode bik (-34 = .)
label define bik 1 "-1,999 inh." ///
2 "2,000-4,999 inh." ///
3 "5,000-19,999 inh." ///
4 "Zone 1-4, -50,000 inh." ///
5 "Zone 2-4, -100,000 inh." ///
6 "Zone 1, -100,000 inh." ///
7 "Zone 2-4, -500,000 inh." ///
8 "Zone 1, -500,000 inh." ///
9 "Zone 2-4, 499,999+ inh." ///
10 "Zone 1, 499,999+ inh.", modify
label var bik "Commuting zone"
// Keep only complete cases
keep if !missing(trust, internet, female, age, isced97, east, foreign, bik)
// See how imbalanced covariates are
// Generate dummies for first table
foreach x of varlist isced97 bik { // Plug in categorical variables here
qui tab `x', gen(`x'x) // Create dummy variables
foreach var of varlist `x'x* {
local lab `: var label `var''
*di "`lab'" // Display label
*di strpos("`lab'", "==")
local i = strpos("`lab'", "==") + 2
local lab `: di substr("`lab'", `i', .)'
di "`lab'"
label var `var' " `lab'" // Add space to label
}
}
// Calculate means
eststo clear
estpost tabstat trust female isced97x* age foreign east bikx*, by(internet) ///
statistics(mean sd) ///
columns(statistics) ///
casewise
// Look at table
esttab, unstack cells(mean(fmt(2)) sd(fmt(2) par keep(trust age))) nonumber ///
label collabels("Mean (SD)/Prop.") modelwidth(25) varwidth(25) ///
refcat(isced97x1 "Education:" bikx1 "Communting zone:", nol)
drop isced97x* bikx* // Drop variables created for table
eststo clear
// Alternative approach
// Run desired model first
qui teffects ipw (trust) (internet east##(c.age##c.age) female foreign ib3.isced97 i.bik, logit)
// Table of covariates
tebalance summarize, baseline // Same table as created above
matrix before = r(table)
matrix list before
// Table of covariates after weighting
tebalance summarize
matrix after = r(table)
matrix list after
// Merge tables
matrix both = before, after
matrix list both
// Look at table
esttab matrix(both, fmt(2)), ///
label nomtitle ///
coeflabel(1.east "Eastern Germany" ///
age "Age" ///
c.age#c.age "Age X age" ///
1.east#c.age "Eastern Germany X age" ///
1.east#c.age#c.age "Eastern Germany X age X age") ///
refcat(1.isced97 "Education:" 2.bik "Commuting zone:", nol) ///
varwidth(30) modelwidth(18) ///
collabel("Control (mean)" "Treated (mean)" "Control (var.)" "Treated (var.)" "Std. diff." "Std. diff. weighted" "Var. ratio" "Var. ratio weighted")
// Omnibus test: tests hypothesis that treatment model balances the covariates
tebalance overid
// Check overlap
teffects overlap, xtitle(Propensity score Internet non-user) ///
ytitle(Density) ///
legend(order(1 "Internet non-user" 2 "Internet user") pos(2) ring(0))
// IPTW
eststo: teffects ipw (trust) (internet east##(c.age##c.age) female foreign ib3.isced97 i.bik, logit), ate
eststo: teffects ipw (trust) (internet east##(c.age##c.age) female foreign ib3.isced97 i.bik, logit), atet
// Doing things by hand:
// Calculate weight for IPTW, ATE
logit internet east##(c.age##c.age) female foreign ib3.isced97 i.bik
predict probab
generate wate = .
replace wate = 1/probab if internet == 1
replace wate = 1/(1 - probab) if internet == 0
// Calculate weight for IPTW, ATT
generate watt = .
replace watt = 1 if internet == 1
replace watt = probab/(1 - probab) if internet == 0
// IPTW by hand
eststo: regress trust i.internet [pw = wate]
eststo: regress trust i.internet [pw = watt]
esttab, b(2) se(2) keep(main:) drop(_cons) rename(r1vs0.internet 1.internet) ///
nobaselevels mtitles("IPTW ATE" "IPTW ATT" "IPTW ATE" "IPTW ATT") ///
mgroup("teffects" "regress", pattern(1 0 1 0))
// Doubly robust
eststo: teffects ipwra (trust east##(c.age##c.age) female foreign ib3.isced97 i.bik) ///
(internet east##(c.age##c.age) female foreign ib3.isced97 i.bik, logit)
eststo: teffects ipwra (trust east##(c.age##c.age) female foreign ib3.isced97 i.bik) ///
(internet east##(c.age##c.age) female foreign ib3.isced97 i.bik, logit), atet
esttab, b(2) se(2) keep(main:) drop(_cons) rename(r1vs0.internet 1.internet) ///
nobaselevels mtitles("IPTW ATE" "IPTW ATT" "IPTW ATE" "IPTW ATT" "IPTW RA ATE" "IPTW RA ATT") ///
mgroup("teffects ipw" "regress" "teffects ipwra", pattern(1 0 1 0 1 0))
// Doubly robust by hand
tempvar internet0a internet1a internet0b internet1b ate att
// ATE
regress trust east##(c.age##c.age) female foreign ib3.isced97 i.bik if !internet [pw = wate]
predict `internet0a'
regress trust east##(c.age##c.age) female foreign ib3.isced97 i.bik if internet [pw = wate]
predict `internet1a'
generate `ate' = (`internet1a' - `internet0a')
summarize `ate'
// ATT
regress trust east##(c.age##c.age) female foreign ib3.isced97 i.bik if !internet [pw = watt]
predict `internet0b'
regress trust east##(c.age##c.age) female foreign ib3.isced97 i.bik if internet [pw = watt]
predict `internet1b'
generate `att' = (`internet1b' - `internet0b')
summarize `att'
Specification curve analysis
use "ZA4612_v1-0-1.dta", clear
do "ZA4612_patch_v1-0-1.do" // Some patch from data provider
keep v399-v404 v933 v827 v301 v298
// Outcomes
mvdecode v399-v404, mv(9 = .a )
generate stress = 5 - v399
generate depress = 5 - v400
generate calm = v401 - 1
generate energy = v402 - 1
generate pain = 5 - v403
generate lonely = 5 - v404
// Predictors
// Topbot
mvdecode v933 v827, mv(96 = .a \ 99 = .b)
generate topbot = v933
replace topbot = v827 if missing(topbot)
// Age
mvdecode v301, mv(999 = .a)
rename v301 age
// Female
generate female = (v298 == 2)
drop v399-v404 v933 v827 v298 // Drop unnecessary variables
// Post definition
tempname foo
postfile `foo' str50 spec k1 k2 k3 b se using deleteme.dta, replace
// Loop
forvalues k1 = 1/6 {
if `k1' == 1 local y "stress"
if `k1' == 2 local y "depress"
if `k1' == 3 local y "pain"
if `k1' == 4 local y "calm"
if `k1' == 5 local y "energy"
if `k1' == 6 local y "lonely"
forvalues k2 = 1/4 {
if `k2' == 1 local agecontrol "age"
if `k2' == 2 local agecontrol "c.age##c.age"
if `k2' == 3 local agecontrol "c.age##c.age##c.age"
if `k2' == 4 local agecontrol "c.age##c.age##c.age##c.age"
forvalues k3 = 1/3 {
if `k3' == 1 local ifs " "
if `k3' == 2 local ifs "if female == 1"
if `k3' == 3 local ifs "if female == 0"
local spec regress `y' topbot `agecontrol' female `ifs'
qui `spec'
local b = _b[topbot]
local se = _se[topbot]
post `foo' ("`spec'") (`k1') (`k2') (`k3') (`b') (`se')
}
}
}
postclose `foo'
// Plot specification curve
use deleteme, clear
// Generate ranked analytical choice variable
sort b
generate sk = _n
label var sk "Specification (sorted by coefficient size)"
// Calculate CI's
generate ub = b + 1.96 * se
generate lb = b - 1.96 * se
// Remind yourself what the variables mean
label var k1 "Outcome"
label var k2 "Age control"
label var k3 "Subsample"
// Stack indicators
generate k3c = k3
generate k2c = k2 + 1 + 3 // 3 because K3 has 3 categories, 1 for title
generate k1c = k1 + 1 + 3 + 4 + 1 // K2 has 4 categories
// Calculate some things for size of second axis
qui summarize b
global brange = r(max) - r(min)
global bmin = r(min)
global bmax = r(max)
global from_y = $bmin - (4.5 * $brange)
// Plot
twoway (scatter k1c k2c k3c sk, msymbol(o o o) msize(vsmall vsmall vsmall) ///
yscale(range(1 22)) ///
ylabel( 1 "Full sample" 2 "Females only" 3 "Males only" 4 "{bf:Subsample}" ///
5 "Age" 6 "Age squared" 7 "Age cubed" 8 "Age quartic" 9 "{bf:Age control}" ///
10 "Stress" 11 "Depression" 12 "Pain" ///
13 "Calmness" 14 "Energy" 15 "Loneliness" 16 "{bf:Outcome}", tstyle(notick) axis(1))) ///
(rcap b b sk, yaxis(2) yscale(range($from_y $bmax) axis(2)) ///
ylab(, format(%2.1g) axis(2)) ///
ytitle("{bf:Coefficient size}", axis(2) placement(north)) ///
yline(0, axis(2))) ///
(rspike ub lb sk, yaxis(2)), ///
xlabel(none) ///
legend(off) name(curve, replace)
Reference
Simonsohn, Uri, Joseph P. Simmons, and Leif D. Nelson. 2015. Specification Curve. Descriptive and Inferential Statistics on All Reasonable Specifications. University of Pennsylvania. doi: 10.2139/ssrn.2694998
Labels:
Allbus,
forvalues,
mvdecode,
postfile,
Textbooks,
twoway rcap,
twoway rspike,
twoway scatter
Oct 18, 2019
Descriptive statistics table using -esttab-
// Open Allbus 1984-2016
use age iscd975 isei* sex using "ZA4586_v1-0-0.dta", clear
// Age
recode age (-32 = .)
label var age "Age"
// Education
recode iscd975 (-32 = .) ///
(1 2 = 0 "Low") ///
(3 4 = 1 "Medium") ///
(5 = 2 "High"), gen(educ)
label var educ "Education"
// ISEI
generate isei = isei88 if inrange(isei88, 16, 90)
replace isei = isei08 if missing(isei) & inrange(isei08, 16, 90)
replace isei = isei68 if missing(isei) & inrange(isei68, 16, 90)
replace isei = isei88a if missing(isei) & inrange(isei88a, 16, 90)
replace isei = isei08a if missing(isei) & inrange(isei08a, 16, 90)
replace isei = isei68a if missing(isei) & inrange(isei68a, 16, 90)
label var isei "ISEI"
// Sex
recode sex (1 = 0 "Male") (2 = 1 "Female"), gen(female)
label var female "Sex"
// Listwise deletion
capture drop touse
mark touse
markout touse age educ sex isei
// Create dummies of categorical variables for descriptives table
foreach x of varlist educ female { // Plug in categorical variables here
qui tab `x', gen(`x'x) // Create dummy variables
foreach var of varlist `x'x* {
local lab `: var label `var''
*di "`lab'" // Display label
*di strpos("`lab'", "==")
local i = strpos("`lab'", "==") + 2
local lab `: di substr("`lab'", `i', .)'
label var `var' "\dumm `lab'" // Add \dumm to label
}
}
// Add this to Latex code to indent dummy variables
// % Indent for tables
// \newcommand*{\dumm}{\hspace*{0.5cm}}%
// Calculate descriptives and save them internally
eststo clear
estpost tabstat isei educx* age femalex* if touse, by(female) ///
statistics(mean sd min max) ///
columns(statistics)
// Format number of cases for table caption
local n: display %9.0gc e(N)
// Create table
esttab using "table1.tex", cells("mean(fmt(2) label(Prop./Mean)) sd(fmt(2) label(\emph{SD}) keep(isei age))") ///
refcat(educx1 "Education:" ///
femalex1 "Sex:", nolabel) ///
coeflabel(isei "Occupational status (ISEI)") ///
unstack ///
order(Total:* Male:* ) ///
nogap eqlabels(, span prefix(\multicolumn{@span}{c}{) suffix(}) erepeat(\cline{@span})) nonumber replace label ///
title("Descriptive statistics, \emph{N}~=~`n' \label{tab1}") ///
stats(N, fmt(%9.0gc) label(\emph{N})) ///
booktabs
drop educx* femalex* // Remove dummy variables created for table
Oct 11, 2019
Indent value labels of categorical variables for -esttab-
// Open Allbus cumulation
use hs01 iscd975 age sex ///
using "ZA4586_v1-0-0.dta", clear
// Self-rated health
recode hs01 (4 5 = 1 "Poor health") ///
(3 2 1 = 0 "Good health") ///
(-1 -11 -9 = .) ///
, gen(poorhealth)
label var poorhealth "Poor self-rated health"
// Education
recode iscd975 (5 = 5 "Tertiary") ///
(4 = 4 "Post-secondary") ///
(3 = 3 "Upper secondary") ///
(2 = 2 "Lower secondary") ///
(1 = 1 "Basic") (-32 = .) ///
, gen(isced)
label var isced "Education"
// Age
recode age (-32 = .)
generate age10 = age/10
label var age10 "Age / 10"
// Sex
recode sex (1 = 0 "Male") ///
(2 = 1 "Female") ///
, gen(female)
label var female "Female sex"
// Indent value labels
labvalch3 female isced, prefix("\dumm ")
// Add this to Latex code
// % Indent for tables
// \newcommand*{\dumm}{\hspace*{0.5cm}}%
eststo clear
eststo: regress poorhealth ib3.isced age10 i.female, robust
esttab using table.tex, b(2) se(2) booktabs replace ///
label nobaselevels nonumber ///
modelwidth(25) varwidth(33) ///
stats(N, fmt(%8.0gc)) ///
refcat(1.isced "Education (ref. Upper secondary)" ///
1.female "Sex (ref. Male)", nol) ///
title("Poor self-rated health regressed on education, age, and sex, linear probability model")
// Alternative approach (that also works for .rtf tables)
labvalch3 female isced, subst("\dumm " "")
*ssc install elabel
elabel define female isced (= #) (= " " + @) , modify
// Note that the leading sapce don't seem to show up in a frequency table with -fre-
esttab using table.rtf, b(2) se(2) replace ///
label nobaselevels nonumber ///
modelwidth(25) varwidth(33) ///
stats(N, fmt(%8.0gc)) ///
refcat(1.isced "Education (ref. Upper secondary)" ///
1.female "Sex (ref. Male)", nol) ///
title("Poor self-rated health regressed on education, age, and sex, linear probability model")
Sep 18, 2019
Random graphs (142): Boxplot using twoway commands with overlaid data
use v358 v392 v585 v829 if inrange(v829, 1, 5) using "data allbus\ZA4612_v1-0-1.dta", clear
// Subjective social mobility
recode v829 (5 = 1 "Much lower status") ///
(4 = 2 "Lower status") ///
(3 = 3 "About equal") ///
(2 = 4 "Higher status") ///
(1 = 5 "Much higher status") ///
(95 96 98 99 = .), gen(ssm)
label var ssm "Status of own job compared to father's"
// Respondent's social status ISEI
clonevar isei = v358
replace isei = . if inlist(isei, 0, 99)
replace isei = v392 if missing(isei)
replace isei = . if inlist(isei, 0, 99)
label var isei "Respondent's ISEI"
// Father's social status ISEI
clonevar fisei = v585
replace fisei = . if inlist(fisei, 0, 99)
label var fisei "Father's ISEI"
// Objective status mobility
gen osm = isei - fisei
label var osm "Objective status mobility"
// Boxplot using -graph- command
graph box osm, over(ssm, descending) horizontal ///
yline(0) l1title("Status of own job compared to father's" "(self-assessment)") ///
name(figure1, replace)
// Boxplot using -twoway- command
// Calculate stuff for boxplot
qui bys ssm: sum osm, detail
qui bys ssm: egen min = pctile(osm), p(25) // Interquartile range
qui bys ssm: egen max = pctile(osm), p(75) // Interquartile range
qui bys ssm: egen med = median(osm)
// Plot
twoway (scatter ssm osm, msymb(o) jitter(2) mcolor(red%10)) ///
(scatter ssm med, msymb(oh) mcolor(black)) ///
(rspike min max ssm, horizontal lcolor(black)), ///
ylabel(1/5, valuelabel) xline(0) ///
ytitle("Status of own job compared to father's" "(self-assessment)") ///
legend(order(2 "Median" 3 "Interquartile range") ring(0) pos(11)) ///
xtitle(Objective social mobility) name(figure2, replace)
drop min max med // Drop stuff for boxplot
Labels:
Allbus,
egen,
graph bar,
Stata 15,
twoway rspike,
twoway scatter
Sep 4, 2018
Making tables for logit models using -esttab-
// Open Allbus 2016 use "ZA5250_v2-0-0.dta", clear // Prepare variables recode hs01 (4 5 = 1 "Poor health") (3 2 1 = 0 "Good health") (-9 = .), gen(poorhealth) label var poorhealth "Poor self-rated health" recode sex (2 = 1 " Female") (1 = 0 " Male"), gen(female) label var female "Female sex" recode age (-32 = .) label var age "Age" recode isced97 (1 2 = 0 " Low") (3 4 = 1 " Medium") (5 6 = 2 " High") (-32 = .), gen(education) label var education "Education" // Fit model 1 eststo clear eststo: qui logit poorhealth i.female i.education age estadd expb qui sum poorhealth estadd scalar avg = r(mean) * 100 // Long table
esttab, cells(b(star fmt(2) label("B")) ///
se(par fmt(2) label("(SE B)")) ///
expb(par([ ]) label("[OR]"))) ///
stats(N avg chi2 df_m, fmt(%8.0gc %8.1f %8.1gc 0) ///
label("Observations" ///
"% poor health" ///
"Chi-squared" ///
"df")) ///
label varwidth(30) modelwidth(25) nonumber nomtitle varlabel(_cons "Intercept") ///
eqlabel(" ") ///
nobaselevel ///
refcat(1.female "Sex (ref. male)" 1.education "Education (ref. low)", nol) ///
addnote("* p<0.05, ** p<0.01, *** p<0.001") ///
title("Poor self-rated health regressed on sex, education, and age. Logistic model")
// Fit models 2
eststo clear
eststo: qui logit poorhealth i.education age if female == 0
qui estadd expb
qui sum poorhealth if female == 0
qui estadd scalar avg = r(mean) * 100
eststo: qui logit poorhealth age i.education if female == 1
qui estadd expb
qui sum poorhealth if female == 1
qui estadd scalar avg = r(mean) * 100
// Wide table
esttab, cell("b(fmt(2) label(B)) se(fmt(2) label(SE B)) expb(fmt(2) label(OR) star)") ///
stats(N avg chi2 df_m, fmt(%8.0gc %8.1f %8.1gc 0) ///
label("Observations" ///
"% poor health" ///
"Chi-squared" ///
"df")) ///
label varwidth(30) modelwidth(8) nonumber mtitle("Men" "Women") varlabel(_cons "Intercept") ///
eqlabel(" ") nobaselevels ///
refcat(1.education "Education (ref. low)", nol) ///
addnote("* p<0.05, ** p<0.01, *** p<0.001") ///
title("Poor self-rated health regressed on education and age, stratified by sex. Logistic model")
Mar 23, 2018
Random graphs (129): Offsetting markers
// Open Allbus 2016
use eastwest hs01 id02 using ZA5250_v2-0-0.dta, clear
// Region
recode eastwest (1 = 0 "West Germany") (2 = 1 "East Germany"), gen(east)
label var east "East Germany"
// Subjective social class
recode id02 (-50/-7 = .) ///
( 1 = 0 "Lower class") ///
( 2 = 1 "Working class") ///
( 3 = 2 "Middle class") ///
( 4 5 = 3 `" "Upper" "(middle)" "class" "'), gen(class)
label var class "Subjective social class"
// Health
recode hs01 (-9 = .) (5 = 0 "Bad") (4 = 1 "Less good") (3 = 2 "Satisfactory") ///
(2 = 3 "Good") (1 = 4 "Very good"), gen(health)
label var health "Self-rated health"
// Model
regress health i.class##i.east //[pw = wghtpew]
// Plot using marginsplot
margins class#east, saving(myfile, replace)
marginsplot, legend(pos(4) ring(0)) name(marginsplot, replace) title("") ///
ytitle("Predicted self-rated health") ylabel(, format(%6.1f))
// Plot using twoway with overlay
use myfile, clear
// Create offset
clonevar _mx = _m1
replace _mx = cond(_m2 == 2, _mx - 0.1, _mx + 0.1)
// Plot using marginsplot
twoway (rcap _ci_lb _ci_ub _m1 if _m2==0, sort) ///
(rcap _ci_lb _ci_ub _mx if _m2==1, sort) ///
(connected _margin _m1 if _m2==0, msymbol(oh)) ///
(connected _margin _mx if _m2==1, msymbol(o)) ///
, title("") ///
ytitle("Predicted self-rated health") xla(, valuelabel) ///
legend(pos(4) ring(0) col(1) order(3 "West Germany" 4 "East Germany")) ///
name(twoway, replace) ylabel(, format(%6.1f))
Labels:
Allbus,
margins,
marginsplot,
Random graphs,
twoway connected,
twoway rcap
Mar 22, 2018
Random graphs (128): Comparing distributions
// Open cumulated Allbus 1980-2014
use ost_west v152 year using ZA4584_v1-0-0.dta, clear
// West Germany only
keep if ost_west == 1
// Subjective SES
recode v152 (0 = .) (97 98 99 = .), gen(topbot)
label var topbot "Subjective SES"
// Drop years with missing data
drop if inlist(year, 1984, 1994, 1996, 1998)
// Drop early years
drop if year < 1998
label drop year // Drop label
// Generate average subjective SES per year
bysort year: egen avg = mean(topbot)
// Figure
tabplot topbot year, yasis xasis horizontal percent barw(1) bfcolor(none) //
xtitle("") subtitle("") note("") //
addplot(connect avg year, sort msymbol(O) mcolor(black) msize(large))
Labels:
Allbus,
Random graphs,
tabplot
Dec 28, 2017
Random graphs (123): Descriptive statistics
// Open Allbus 2010
use v11 v13 v15 v17 v19 using ZA4612_v1-0-1.dta, clear
// Prepare variables
recode v11 v13 v15 v17 v19 (99 = .)
label define x 1 `""1" "Unimportant""' 7 `""7 Very" "important"'
label var v11 "v11: Job security"
label var v13 "v13: High income"
label var v15 "v15: Opportunities for promotion"
label var v17 "v17: Respectable occupation"
label var v19 "v19: Lots of leisure time"
// Plot histograms
foreach x of varlist v11 v13 v15 v17 v19 {
label val `x' x
histogram `x', frequency ///
xlabel(1 (1) 7, val) ///
ylabel(0 (500) 1500) ///
ytick(0 (250) 1750) ///
name(`x', replace) nodraw
}
// Calculate correlation matrix
cor v11-v19
matrix correlations = r(C)
// Plot correlation matrix
plotmatrix, mat(correlations) split(-1(0.10)1) color(sienna) ///
freq formatcells(%6.2f) nodiag legend(title(Pearson's {it:r}) col(1)) ///
name(cormatrix, replace) nodraw
// Combine plots
graph combine v11 v13 v15 v17 v19 cormatrix, col(2) ysize(8) xsize(6) altshrink
Labels:
Allbus,
Correlation tables,
Histogram,
plotmatrix,
Random graphs
Dec 3, 2017
Random graphs (121): Overlaid prediction plots
// Open cumulated Allbus 2004-2014
use if year >= 2004 using "ZA4584_v1-0-0.dta", clear
// Select data
keep if inrange(v729, 25, 65) // Only those between 25 and 65
drop if v495 == 0 // Health split
// Poor self-rated health
generate poorhealth = inlist(v495, 4, 5) if !inlist(v495, 0, 9)
// Top-bottom
recode v152 (0 99 = .), gen(sss)
label define sss 1 `""1" "Bottom""' 2 "2" 3 "3" 4 "4" 5 "5" 6 "6" 7 "7" 8 "8" 9 "9" 10 `""10" "Top""'
label val sss sss
label var sss "Subjective SES"
// Education
recode v767 (94 99 = .), gen(educ)
label define educ 1 "Basic" 2 "Lower secondary" 3 "Upper secondary" 4 "Post-secondary" 5 "Tertiary"
label val educ educ
label var educ "Education"
// ISEI 1988
generate isei = v789 if !inlist(v789, 0, 99)
replace isei = v825 if missing(isei) & !inlist(v825, 0, 99)
label var isei "Occupational status (ISEI)"
// EGP
recode v784 (0 = .a) (10004 = .b) (10009 = .c) (1 2 = .d) // ISCO-88
recode v820 (0 = .a) (10004 = .b) (10009 = .c) (1 2 = .d) // Last job ISCO-88
clonevar isco88 = v784
replace isco88 = v820 if missing(isco88) & !missing(v820)
recode v804 (0 = .a "Not available") (9999 = .b "No answer"), gen(supervisor) // Number of people supervised
recode v773 (0 = .a "Not available") (99 = .b "No answer") ///
(10/24 = 1 "Self-employed") (40/65 = 0 "Employed") ///
(30 70/74 = .c "Not employed"), gen(selfemployed) // Self-employed
iskoegp egp, isko(isco88) supvis(supervisor) sempl(selfemployed)
// Household income
generate income = v924+1 if !inlist(v924, 99996, 99997, 99999)
generate lninc = log(income)
label var lninc "Household income (logged, equivalized)"
// Controls
generate state = v1374
generate female = (v731 == 2)
generate age = v729 if v729 != 999
// Macro for controls
local control i.female c.age##c.age i.state##i.year
// Fit some models
eststo clear
qui eststo: logit poorhealt sss `control', robust cluster(year)
qui margins, over(sss) post
est store model1
eststo: logit poorhealt sss i.educ `control', robust cluster(year)
qui margins, over(sss) post
est store model2
eststo: logit poorhealt sss i.educ isei `control', robust cluster(year)
qui margins, over(sss) post
est store model3
eststo: logit poorhealt sss i.educ isei i.egp `control', robust cluster(year)
qui margins, over(sss) post
est store model4
eststo: logit poorhealt sss i.educ isei i.egp lninc `control', robust cluster(year)
qui margins, over(sss) post
est store model5
// Plot findings
coefplot model1 model2 model3 model4 model5, vertical ///
legend(order(2 "Age, federal state, survey year" 4 "plus Education" ///
6 "plus occupational status (ISEI)" ///
8 "plus social class (EGP)" ///
10 "plus household income") pos(2) ring(0) col(1) ///
title(Model accounting for)) ///
scheme(plotplainblind) ///
xtitle(Subjective socioeconomic status) ///
ytitle(Predicted probability of poor health)
Labels:
Allbus,
coefplot,
estimates store,
iskoegp,
margins,
Random graphs
Aug 13, 2017
Random graphs (110): Correlation heatmap
// Open Allbus 2010 data
use "ZA4612_v1-0-1.dta", clear
// Men 25-64 only
keep if v298 == 1
keep if inrange(v301, 20, 64)
// Combine top bottom variables into one
// (Seems pointless, though, as education in years
// was only measured in one of the splits)
generate topbot = v933 if v933 <= 10
replace topbot = v827 if missing(topbot)
replace topbot = . if topbot > 10
// Education, truncated to 5th-95th percentile
qui sum v917 if v917 < 94, detail
generate education = v917 if v917 < 94
replace education = r(p95) if education >= r(p95) & !missing(education)
replace education = r(p95) if education >= r(p95) & !missing(education)
replace education = r(p5) if education <= r(p5) & !missing(education)
// ISEI
generate isei88 = v358 if !inlist(v358, 0, 99)
replace isei88 = v392 if !inlist(v392, 0, 99)
// Household income, logged
generate income = v674 if !inlist(v674, 99997, 99999)
generate lnincome = log(income)
// Generate correlation matrix
cor topbot education income isei
matrix correlations = r(C)
// Plot
plotmatrix, mat(correlations) split(-1(0.10)1) color(vermillion) ///
freq formatcells(%6.2f) nodiag legend(title(Pearson's {it:r}) col(1))
Labels:
Allbus,
correlate,
Correlation tables,
plotmatix,
Random graphs
Aug 9, 2017
Random graphs (108): Violin plot
// Open Allbus data
use V388 V151 using "ZA4602_v1-0-0.dta", clear
// Income
recode V388 (99997 = .a "Refused") (99999 = .b "No answer"), gen(personal_income)
label var personal_income "Personal net income"
// Sex
recode V151 (1 = 0 "Men") (2 = 1 "Women"), gen(sex)
label var sex "Gender"
vioplot personal_income, over(sex) ytitle("Personal net income in Euro per month")
Labels:
Allbus,
Random graphs,
vioplot
Jul 27, 2017
Random graphs (106): Interaction plot with overlaid density
// Open Allbus 2008
use V154 V151 V156 V760 V754 V755 V5 V767 using ZA4602_v1-0-0.dta, clear
// Age
generate age = V154 if V154 != 999
// Sex
generate female = (V151 == 2)
// Migrant
generate migrant = (V156 == 2)
// Interviewer ID
rename V760 id
// Interviewer sex
generate femaleinterviewer = (V754 == 2)
// Interviewer age
generate interviewerage = V755
// Attractiveness rating by interviewer before and after interview
qui factor V5 V767, pcf
predict attractiveness
// Calculate Spearman-Brown for two-item scales according
// to Eisinga et al. (https://doi.org/10.1007/s00038-012-0416-3):
spearman V5 V767
// Fit model with respondents clustered in interviewers
mixed attractiveness c.age##i.female i.migrant i.femaleinterviewer##c.interviewerage || id:
// Calculate margins and plot
qui margins, at(age = (18 (10) 98) female = (0 1))
marginsplot, recast(line) recastci(rarea) ciopt(color(gs14)) ///
plot1opts(lpattern(dash)) ///
legend(ring(0) pos(2)) ///
title("Female beauty premium disappears with age", span) ///
ytitle("Predicted attractiveness", axis(1)) ///
xtitle("Age") ///
xlabel(20 (10) 100) ///
addplot(histogram age, discrete yaxis(2) ///
lcolor(white) ///
ylabel(0 0.01 0.02, format(%6.2f) axis(2)) ///
yscale(alt range(0 0.1) axis(2)) ///
ytitle("Age density", axis(2)) ///
legend(order(3 "Men" 4 "Women"))) ///
note(" " "{it:Source:} German General Social Survey Allbus 2008, doi:10.4232/1.12345", span) ///
name(figure1, replace)
Jul 22, 2017
Random graphs (104): Sunflower plot
// Open Allbus data
use v614 v301 using "C:\Users\User\Dropbox\methods and data\allbus\ZA4612_v1-0-1.dta", clear
// Prepare variables
recode v301 (999 = .), gen(age)
label var age "Age"
recode v614 (99997 99999 = .), gen(personal_income)
label var personal_income "Personal net income in Euro"
// Sunflower plot
sunflower personal_income age, legend(pos(11) ring(0) size(*.9)) ///
note(" " "{it:Source:} German General Social Survey Allbus 2010, doi:10.4232/1.11782", span)
Labels:
Allbus,
Random graphs,
sunflower
Random graphs (103): Dot plots
// Open Allbus data
use V388 V151 using "ZA4602_v1-0-0.dta", clear
// Income
recode V388 (99997 = .a "Refused") (99999 = .b "No answer"), gen(personal_income)
label var personal_income "Personal net income"
// Sex
recode V151 (1 = 0 "Men") (2 = 1 "Women"), gen(sex)
label var sex "Gender"
// Dotplot stratified by grouping variable
dotplot personal_income, over(sex) center msymbol(oh) ///
ytitle("Personal net income in Euro") xtitle("") ///
note(" " "{it:Source:} German General Social Survey Allbus 2008, doi:10.4232/1.12345", span) ///
name(figure1, replace)
// Open EQLS data
use Y11_Q40b Y11_Q40e Y11_Q40f Y11_Q40g Y11_Q30 using "7348_F1.dta", clear
// Relabel variables
label var Y11_Q40b "Job"
label var Y11_Q40e "Family life"
label var Y11_Q40f "Health"
label var Y11_Q40g "Social life"
label var Y11_Q30 "Life overall"
// Dotplot for several variables
dotplot Y11_Q40b Y11_Q40e Y11_Q40f Y11_Q40g Y11_Q30, ///
ylabel(1 "Very dissatisfied 1" 2 3 4 5 6 7 8 9 10 "Very satisfied 10") ///
xtitle("How satisfied with ...") ///
note("{it:Source:} European Quality of Life Survey 2003-12", span) ///
name(figure2, replace)
Labels:
Allbus,
dotplot,
EQLS,
Random graphs
Jul 10, 2017
Random graphs (102): Sparklines
use v151 year ost_west if ost_west == 1 using ZA4582_v1-0-0.dta, clear
// Year
label drop year
label var year ""
// Subjective social class
recode v151 (9 = .a "No response") ///
(8 = .b "Don't know") ///
(7 = .c "Refused") ///
(6 = .d "None of the strata") ///
(5 = 5 "Upper class") ///
(4 = 4 "Upper middle class") ///
(3 = 3 "Middle class") ///
(2 = 2 "Working class") ///
(1 = 1 "Lower class") ///
, gen(subjclass)
label var subjclass "Subjective social class"
qui tab subjclass, gen(subjx)
// Change value labels in bulk
foreach var of varlist subjx* {
local lab `: var label `var''
local lab `: di subinstr("`lab'", "subjclass==", " ", 1)'
label var `var' "`lab'"
}
// Collapse data set
// Copy variable labels before collapse
// Following:
// http://www.stata.com/support/faqs/data-management/keeping-same-variable-with-collapse/
foreach var of var subjx* {
local l`var' : variable label `var'
if `"`l`var''"' == "" {
local l`var' "`var'"
}
}
// Collapse
collapse subjx*, by(year)
// Restore value labels after collapse
foreach var of var subjx* {
label var `var' "`l`var''"
}
// Change to percentages
foreach var of var subjx* {
replace `var' = `var' * 100
}
// Sparklines
sparkline subjx* year, variablelabels xlabel(1980 (10) 2010) xmtick(1980 (2) 2014) ///
xtitle("") format(%6.1f) extremes ///
title("Subjective social class in Western Germany", span) ///
name(subjclass, replace)
Jun 6, 2017
Comparing AME's and the LPM
use doi hs01 age sex educ mstat using ZA5250_v2-0-0.dta, clear
// Poor health
recode hs01 (1 2 3 = 0 "Non-poor health") ///
( 4 5 = 1 "Poor health") ///
(-9 = .), gen(poorhealth)
label var poorhealth "Poor health"
// Female sex
recode sex (2 = 1 "Female") ///
(1 = 0 "Male"), gen(female)
label var female "Female sex"
// Age
recode age (18/24 = 0 "18-24 y.") ///
(25/34 = 1 "25-34 y.") ///
(35/44 = 2 "35-44 y.") ///
(45/54 = 3 "45-54 y.") ///
(55/64 = 4 "55-64 y.") ///
(65/74 = 5 "65-74 y.") ///
(75/84 = 6 "75-84 y.") ///
(85/97 = 7 "85-97 y.") ///
(-32 = . ), gen(agecat)
label var agecat "Age"
// Education
recode educ (1 2 = 0 "Hauptschule or less") ///
( 3 = 1 "Mittlere Reife") ///
(4 5 = 2 "(Fach)Hochschulreife or more") ///
(-41 -9 6 7 = .), gen(education)
label var education "Education"
// Marital status
recode mstat (1 6 = 2 "Married/cohabiting") ///
(2 3 4 9 = 1 "Divorced, widowed etc.") ///
(5 = 0 "Never married") ///
(-9 = .), gen(married)
label var married "Marital status"
// Model
eststo clear
// AME
logit poorhealth i.female i.agecat i.education i.married
margins, dydx(*) post
eststo
// LPM
eststo: regress poorhealth i.female i.agecat i.education i.married, robust
esttab using amelpm.tex, drop(_cons) mtitle("AME" "LPM") label b(2) se(2) nonumbers booktabs ///
title("Predictors of poor self-rated health, Germany 2016 \label{tab1}") ///
addnote("\emph{Source}: Allbus 2016, doi: 10.4232/1.12754" ///
"AME: Average marginal effects, LPM: Linear probability model") ///
refcat(0.female "\emph{Sex}" ///
0.agecat "\emph{Age}" ///
0.education "\emph{Education}" ///
0.married "\emph{Marital status}", nolabel) ///
alignment(D{.}{.}{-1}) width(0.9\hsize) replace
May 24, 2017
Random graphs (95): Categorical variables
use "ZA4582_v1-0-0.dta", clear
recode v151 (9 = .a "No response") ///
(8 = .b "Don't know") ///
(7 = .c "Refused") ///
(6 = .d "None of the strata") ///
(5 = 1 "Upper class") ///
(4 = 2 "Upper middle class") ///
(3 = 3 "Middle class") ///
(2 = 4 "Working class") ///
(1 = 5 "Lower class") ///
, gen(subjclass)
label var subjclass "Subjective social class"
generate nolabelyear = year
label define ost_west 1 "Western Germany" 2 "Eastern Germany", modify
graph bar (count), over(subjclass, descending) ///
over(nolabelyear, label(angle(vertical))) ///
by(ost_west, note("{it:Source:} German General Social Survey (Allbus), doi: 10.4232/1.12439.", span) col(1)) ///
percent stack asyvars ytitle(%) ysize(8) ///
legend(rows(3) colfirst) name(figure1, replace)
tabplot subjclass nolabelyear, by(ost_west, ///
note("{it:Source:} German General Social Survey (Allbus), doi: 10.4232/1.12439.", span)) ///
percent(ost_west nolabelyear) ///
showval(mlabsize(tiny)) xtitle("") ///
xlabel(, angle(vertical)) name(figure2, replace)
Labels:
Allbus,
graph bar,
Random graphs,
tabplot
May 28, 2016
Random graphs (87): Line plots
unzipfile ZA4582_v1-0-0.dta.zip
use ZA4582_v1-0-0.dta, clear
// Prepare some variables
recode v442 (0 = .a "Not asked") ///
(1 = 3 "Daily") ///
(2 = 2 "At least once per week") ///
(3 = 1 "At least once per month") ///
(4 5 = 0 "Less often/never") ///
(9 = .b "No answer"), generate(internet_inc1998)
recode v462 (0 = .a "Not asked") ///
(1 = 3 "Daily") ///
(2 = 2 "At least once per week") ///
(3 = 1 "At least once per month") ///
(4 5 = 0 "Less often/never") ///
(9 = .b "No answer"), generate(internet_inc2014)
recode v1910 (0 = .a "Not asked") ///
(1 = 3 "Daily") ///
(2 = 8 "Several times a week") ///
(3 = 2 "At least once per week") ///
(4 = 1 "At least once per month") ///
(5 = 0 "Less than once per week") ///
(9 = .b "No answer"), generate(internet_inc2006)
recode v1909 (0 = .a "Missing") ///
(1 = 1 "Yes") ///
(2 = 0 "No"), gen(internet_prev2006)
// Daily and weekly usage
clonevar internet_inc = internet_inc1998
replace internet_inc = internet_inc2014 if year == 2014
preserve
qui tab internet_inc, gen(usage)
rename usage4 dailyusage
rename usage3 weeklyusage
collapse dailyusage weeklyusage, by(year)
replace dailyusage = dailyusage * 100
replace weeklyusage = weeklyusage * 100
drop if missing(dailyusage)
twoway (scatter weeklyusage year, connect(L)) ///
(scatter dailyusage year, connect(L)) ///
, legend(order(1 "At least once per week" ///
2 "Daily") title("Internet usage", size(*.8)) ring(0) pos(11)) ///
xlabel(1998 2004 2014) xtitle("") ytitle(%) ylabel(0 (10) 60) ///
note(" " "{it:Source:} German General Social Survey (Allbus), doi: 10.4232/1.12439" ///
"{it:Note:} Based on recodings of v442 and v462.", span) name(internet1, replace)
restore
// Daily internet usage based on different response formats
replace internet_inc = internet_inc2006 if year == 2006 | year == 2008
preserve
qui tab internet_inc, gen(usage)
rename usage4 dailyusage
collapse dailyusage, by(year)
replace dailyusage = dailyusage * 100
drop if missing(dailyusage)
twoway (scatter dailyusage year, connect(L)) ///
, xlabel(1998 2004 2006 2008 2014) xtitle("") ytitle("% of respondents reporting" "{bf:daily} internet usage") ylabel(0 (10) 60) ///
note(" " "{it:Source:} German General Social Survey (Allbus), doi: 10.4232/1.12439" ///
"{it:Note:} Based on recodings of v442, v462, and v1910.", span) name(internet2, replace)
restore
// Yes/no question
preserve
collapse internet_prev, by(year)
drop if missing(internet_prev)
replace internet_prev = internet_prev * 100
twoway (scatter internet_prev year, connect(L)) ///
, xlabel(2006 2008 2010 2012 2014) xtitle("") ytitle("% of respondents using the internet") ylabel(0 (10) 80) ///
note(" " "{it:Source:} German General Social Survey (Allbus), doi: 10.4232/1.12439. {it:Note:} Based on v1909.", span) ///
name(internet3, replace)
restore
erase ZA4582_v1-0-0.dta
Labels:
Allbus,
collapse,
Random graphs,
twoway scatter
Subscribe to:
Posts (Atom)






















