* Drawing regression lines sysuse auto * think of "lfit" as data transformed by the graphics routine twoway (scatter price mpg) (lfit price mpg), title("lfit") name(g1) * think of "function" as theoretical data regress price mpg twoway (scatter price mpg) /// (function y= _b[_cons]+_b[mpg]*x, range(mpg)), title("function") name(g2) * and "line" connects points in the data set predict pricehat label variable pricehat "Predicted price" sort mpg twoway (scatter price mpg) (line pricehat mpg), title("line") name(g3) drop pricehat * "marginsplot" is a cousin to these margins, at(mpg= (12(2)40)) marginsplot, ylabel(0(5000)16000) xlabel(10(10)41) title("marginsplot") name(g4) graph combine g1 g2 g3 g4, title("Regression line alternatives") graph drop g1 g2 g3 g4 * It is easier to draw a graph with all interactions in the model * than without some interactions * Perhaps the most straightforward: twoway (scatter price mpg) (lfit price mpg if foreign==0) /// (lfit price mpg if foreign==1), legend(label(1 "Price") /// label(2 "Domestic") label(3 "Foreign")) * Even easier with faceting/paneling * (but not as easy to compare the lines) twoway (scatter price mpg) (lfit price mpg), by(foreign) * Similar to the above generate price0 = price if foreign==0 label variable price0 "Domestic" generate price1 = price if foreign==1 label variable price1 "Foreign" twoway (scatter price mpg) (lfit price0 mpg) (lfit price1 mpg), /// legend(label(1 "Price") label(2 "Domestic") label(3 "Foreign")) drop price0 price1 * This might be a good approach if you wanted to automate, * since it uses only one "line" call regress price c.mpg##i.foreign predict yhat generate price0hat = yhat if foreign==0 label variable price0hat "Domestic" generate price1hat = yhat if foreign==1 label variable price1hat "Foreign" twoway (scatter price mpg) (line price0hat price1hat mpg) drop yhat price0hat price1hat * Perhaps useful for pedagogical purposes twoway (scatter price mpg) (function y= _b[_cons]+_b[mpg]*x, range(mpg)) /// (function y= (_b[_cons]+_b[1.foreign]) + (_b[mpg]+_b[1.foreign#c.mpg])*x, /// range(mpg)), legend(label(1 "Price") label(2 "Domestic") label(3 "Foreign")) margins foreign, at(mpg= (12(2)40)) marginsplot, ylabel(0(5000)16000) xlabel(10(10)41) title("marginsplot") name(g4) * Additive versions of the model above * Simply using "lfit" is no longer an option! * We can use the same multi y "line" as above regress price mpg i.foreign predict yhat label variable yhat "Predicted price" generate pricehat0 = yhat if foreign==0 label variable pricehat0 "Domestic" generate pricehat1 = yhat if foreign==1 label variable pricehat1 "Foreign" sort mpg twoway (scatter price mpg) (line pricehat0 pricehat1 mpg) * using "line" give us the easiest multi-panel version twoway (scatter price mpg) (line yhat mpg), by(foreign) * Fairly compact for small numbers of categories, but awkward * for many categories twoway (scatter price mpg) (line yhat mpg if foreign==0) /// (line yhat mpg if foreign==1), /// legend(label(1 "Price") label(2 "Domestic") label(3 "Foreign")) drop yhat pricehat0 pricehat1 * Again, the pedagogical version twoway (scatter price mpg) (function y= _b[_cons]+_b[mpg]*x, range(mpg)) /// (function y= (_b[_cons]+_b[1.foreign]) + (_b[mpg])*x, /// range(mpg)), legend(label(1 "Price") label(2 "Domestic") label(3 "Foreign")) * Add a second categorical variable * What model is this? twoway (scatter price mpg) (lfit price mpg), /// by(rep78 foreign, rows(5) holes(2 4)) regress price c.mpg##foreign##rep78 test c.mpg#1.foreign#3.rep78 c.mpg#1.foreign#4.rep78 /// 1.foreign#3.rep78 1.foreign#4.rep78 /// 2.rep78#c.mpg 3.rep78#c.mpg 4.rep78#c.mpg 5.rep78#c.mpg /// 1.foreign#c.mpg /// 1.foreign 2.rep78 3.rep78 4.rep78 5.rep78 // c.mpg regress price c.mpg##(foreign rep78) foreign#rep78 test 1.foreign#3.rep78 1.foreign#4.rep78 /// 2.rep78#c.mpg 3.rep78#c.mpg 4.rep78#c.mpg 5.rep78#c.mpg /// 1.foreign#c.mpg regress price mpg i.foreign i.rep78 test 1.foreign 2.rep78 3.rep78 4.rep78 5.rep78 regress price mpg predict yhat sort mpg twoway (scatter price mpg) (line yhat mpg), /// by(rep78 foreign, rows(5) holes(2 4)) drop yhat * Ignore the tests, suppose we wanted to panel by foreign * and have multiple lines by rep78 in an additive (first * order terms only) model? regress price mpg i.foreign i.rep78 predict yhat levelsof rep78, local(rlvl) foreach lvl of local rlvl { generate rep`lvl' = yhat if rep78==`lvl' label variable rep`lvl' "`lvl'" } twoway (scatter price mpg) (line rep? mpg), by(foreign) drop rep? yhat