Note how this is restricted to the linear decompositions!
Intracohort change versus overall change

use year race age cohort racmar using GSS7214_R4.DTA, clear
// Select sample
keep if inlist(year, 1974, 1984, 1994)
keep if race == 1 // Whites only
keep if age >= 20
keep if !missing(age, racmar)
// Generate 10-year cohort variable
generate cohort10 = .
local lowerbracket = 1965
local upperbracket = 1974
foreach x of numlist 1/10 {
replace cohort10 = `x' if cohort >= `lowerbracket' & cohort <= `upperbracket'
label define cohort10 `x' "`lowerbracket' to `upperbracket'", modify
local lowerbracket = `lowerbracket' - 10
local upperbracket = `upperbracket' - 10
}
label value cohort10 cohort10
label var year "Year"
// Opposing interracial marriage
recode racmar (1 = 1 "Yes") (2 = 0 "No") (.d .i .n = .), gen(oppose)
label var oppose "Opposes interracial marriage"
generate oppose_perc = oppose * 100
// Create Table 4.1 without change
table cohort10 year, contents(mean oppose_perc n oppose_perc) format(%9.1f) center
// Different version of Table 4.1, including calculated changed
preserve
qui table cohort10 year, contents(mean oppose_perc n oppose_perc) format(%9.1f) center replace
rename table1 oppose_perc
rename table2 oppose_n
reshape wide oppose_perc oppose_n, i(cohort10) j(year)
gen change1984 = oppose_perc1984 - oppose_perc1974
gen change1994 = oppose_perc1994 - oppose_perc1984
format change1984 change1994 %9.1f
list, noobs sep(0) abbreviate(20) subvar
restore
Empirical example for linear decomposition: Trend in antiblack prejudice

use year race cohort racdin racpush racseg racmar using GSS7214_R4.DTA, clear
// Create sample
keep if inlist(year, 1972, 1976, 1980, 1984)
keep if race == 1
// Create outcome
alpha racdin racpush racseg racmar, item
egen zracdin = std(racdin)
egen zracpush = std(racpush)
egen zracseg = std(racseg)
egen zracmar = std(racmar)
scores y = total(zracdin zracpush zracseg zracmar), minvalid(3)
gen prejudice = 6 - y // Difficult to figure out the exact outcome
drop y // But this seems to be close enough
// Calculate total change in prejudice
mean prejudice, over(year) coeflegend
local totalchange = _b[1984] - _b[1972]
// Calculate annual change within cohorts
reg prejudice year cohort
local b1 = _b[year]
local b2 = _b[cohort]
// Calculate contributions of intracohort change and cohort replacement
local intracohort = `b1' * (1984 -1972)
di `intracohort'
qui mean cohort, over(year) coeflegend
local cohortreplacement = `b2' * (_b[1984] - _b[1972])
di `cohortreplacement'
// Calculate estimated total change
local estim_change = `intracohort' + `cohortreplacement'
di `estim_change'
// Output results
matrix results = (`totalchange')\(`b1')\(`b2')\(`intracohort')\(`cohortreplacement')\(`estim_change')
esttab matrix(results, fmt(%9.2f)), coeflabel(r1 "Total change" ///
r2 "Intracohort slope" ///
r3 "Intercohort slope" ///
r4 "Estimated contribution of intracohort change" ///
r5 "Estimated contribution of cohort replacement" ///
r6 "Estimated total change") ///
mtitle("Result") ///
varwidth(45)
Empirical example of the same-sign rule: Gender role attitudes
use year cohort fework fepres fepol fehome if year >= 1972 & year <= 1988 using GSS7214_R4.DTA, clear
// Prepare variables
recode fework fepres (2 = 0)
recode fepol fehome (2 = 1) (1 = 0)
// Create sample for Table 4.2
preserve
keep if inlist(year, 1972, 1974, 1988)
fre year
gen id = _n
reshape wide fework fepres fepol fehome, i(id) j(year)
replace fepol1972 = fepol1974
replace fehome1972 = fehome1974
reshape long
drop if year == 1974
recode year (1972 = 0 "1972") (1988 = 1 "1988"), gen(yr)
// Table 4.2

foreach y of varlist fework fepres fepol fehome {
qui regress `y' yr
local mean1972 = _b[_cons]
local mean1988 = _b[_cons] + _b[yr]
local differen = _b[yr]
local t = _b[yr] / _se[yr]
*di "`y'" _skip(5) `mean1972' _skip(5) `mean1988' _skip(5) `differen' _skip(5) `t'
matrix stuff1 = (`mean1972' , `mean1988' , `differen' , `t')
if "`y'" == "fework" matrix table42 = stuff1
else matrix table42 = (table42\stuff1)
}
matrix rownames table42 = "WORK" "PRES" "POLI" "HOME"
matrix colnames table42 = "Mean 1972" "Mean 1988" "Change" "t-value"
esttab matrix(table42, fmt(3 3 3 1))
restore
// Table 4.3
foreach y of varlist fework fepres fepol fehome {
qui logit `y' year cohort
local n = e(N)
local intracohort = _b[year]
local intracohort_t = _b[year] / _se[year]
local intercohort = _b[cohort]
local intercohort_t = _b[cohort] / _se[cohort]
*di "`y'" _skip(5) `n' _skip(5) `mean1988' _skip(5) `differen' _skip(5) `t'
matrix stuff = (`n', `intracohort', `intracohort_t', ///
`intercohort', `intercohort_t')
if "`y'" == "fework" matrix table43 = stuff
else matrix table43 = (table43\stuff)
}
matrix rownames table43 = "WORK" "PRES" "POLI" "HOME"
matrix colnames table43 = "N" "Within cohort" "t" "Cross-cohort" "t"
esttab matrix(table43, fmt(0 %9.3f %9.1f %9.3f %9.1f)), modelwidth(14)
Reference
Firebaugh, Glenn. 1997. Analyzing Repeated Surveys. Sage. doi: 10.4135/9781412983396