Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problems creating certain LaTeX tables with huge looping code through matrices

    I have to work with some code that isn't mine and that uses a lot of loops to create a table.
    To put it in context, I first need to create a
    • (i) first-stage table and
    • (ii) then do a two-stage least squares (econometrics fans will certainly be familiar with this).
    Problem: the code is complex and when I run the code, the saved table contains some duplicated variables and the table is a mess, in particular for the 2sls regression.

    As for the first-stage table, the regressions are correct and everything comes out as it should.

    However, for the 2sls, the table is not what you would expect. Here is a small set of data corresponding to the variables of interest here. The code below is also used.

    Could you please help me? I've been stuck on this for a while and don't know how to solve the problem. Many thanks in advance.


    Code:
    * Example generated by -dataex-. For more info, type help dataex
    clear
    input float(pop_00_03 pop_04_14 pop_04_22 pop_16_22 cumpower_solar_norm_06_14 cumpower_solar_norm_06_22 cumpower_solar_norm_18_22) double com_pv_potential float(com_sensitivity_solar_1 inter_solar_above_1 prov_code)
     -207  1469  1002  -324     .2067     .2067         0  1213.258903503418 1 1213.2589  1
      646  1175  1554   344     .9285     .9285         0 1266.2647552490234 1 1266.2648  1
      366   686   896   344    2.6577   26.6727        24 1314.7562217712402 1 1314.7562  1
     6649 21947 34186  9625   6.66833   7.34433  .6000004 1316.0530490875244 1  1316.053  1
       31  -114    23   215     .4492     .4492         0 1339.9544219970703 1 1339.9545  1
      378   864   846    82    1.8905 2.1185002 .22800016 1430.6792602539063 1 1430.6792  1
     3875  5451  1755 -2642     26.74  614.3524 587.61237 1669.8718795776367 1  1669.872 10
      244 -1230 -3825 -1990   54.3235  585.7555   531.432   1661.23876953125 1 1661.2388 10
     -338  -886 -1870  -738    7.3299  280.7089   273.379 1653.3397336006165 0         0 10
     -287  -914 -1924  -769      2.59     86.59        84 1662.4372177124023 0         0 10
    -1188 -1589 -2964  -994  235.6368  363.2628   127.626 1642.3391647338867 1  1642.339 10
     1405  -608 -2278 -1300 111.68807  613.2584  501.5549 1655.7666759490967 1 1655.7667 10
      509 -1348 -2319  -592   4.13814   4.13814         0 1638.1639709472656 1  1638.164 10
     1089  1588 -1823 -2937   10.7538    77.474   66.7202 1642.0976028442383 1 1642.0977 10
     -562  -664 -2313 -1236       1.7     2.855 1.1549999 1597.5255527496338 1 1597.5255 10
    -1531 -2487 -6024 -2662  21.85632  21.87874         0  1630.155107975006 1  1630.155 10
    12404 30402 30496   438 132.26796  467.3235    334.93  1561.922212600708 1 1561.9222 11
     3967 20492 19475  1431   9.60316   9.60316         0 1738.1756172180176 1 1738.1757 11
      -89  -885 -2954 -1544      2.78  2.880585  .0999999 1670.3062381744385 1 1670.3063 11
     2508  5970  6047   448   14.2629 244.69165 230.42876 1688.9799499511719 1   1688.98 11
    11829 19822 29343  6119   13.9427  14.14255         0 1629.9501266479492 1   1629.95 11
     -164  -588 -1136  -204    2.5619    2.5619         0 1579.6495881080627 0         0 12
      333  -626 -1921  -832 2.1876001 2.1876001         0 1573.5992584228516 1 1573.5992 12
      244  2535  2557   313   16.0095   16.0095         0 1597.2728004455566 1  1597.273 12
      747   341  -142  -233     .3982     .3982         0 1607.2020378112793 1  1607.202 12
    end


    Code:
    *****************************************************
    * 2. Define some macros for further reg and 2sls
    *****************************************************
    
    local inst = 1                                                            // = 1 use environmental sustainability index above one as instrument
                                                                                    // = 2 use solar/wind potential
                                                                                    // = 3 use interaction
                                                                                    // = 4 use 1; 2 & 3 together
    
    local energy = 1                                                       // = 1 if solar
                                                                                    // = 2 if wind
    // Estimation
    *local vlist "logpop pop immig_flow emig_flow births"
    local vlist "pop"
    foreach x of local vlist {
        if "`x'" == "pop" {
            local title "Change in population"
        }
        else if "`x'" == "logpop" {
            local title "Log change in population"
        }    
        else if "`x'" == "immig_flow" {
            local title "In-migrations (cumulative over)"
        }    
        else if "`x'" == "emig_flow" {
            local title "Out-migrations (cumulative over)"
        }    
        else {
            local title "Births (cumulative over)"
        }    
        
    *****************************************************
    * 3. We focus here on solar (`energy' = 1)
    *****************************************************
    
    
        if `energy' == 1 {
        
            eststo clear
            forvalues j = 1 / 3 {
                if `inst' == 1 {
                    if `j' == 1 {
                        local kreg "cumpower_solar_norm_06_22"
                    }
                    else if `j' == 2 {
                        local kreg "cumpower_solar_norm_06_14"        
                    }
                    else {
                        local kreg "cumpower_solar_norm_18_22"    
                    }
                    local iv "com_sensitivity_solar_1"                            
                    local labtitle "envsustain_above_one"
                }    
                else if `inst' == 2 {        
                    if `j' == 1 {
                        local kreg "cumpower_solar_norm_06_22"
                    }
                    else if `j' == 2 {
                        local kreg "cumpower_solar_norm_06_14"
                    }
                    else {
                        local kreg "cumpower_solar_norm_18_22"    
                    }
                    local iv "com_pv_potential"            
                    local labtitle "solar_potential"            
                }
                else if `inst' == 3 {
                    if `j' == 1 {
                        local kreg "cumpower_solar_norm_06_22"
                    }
                    else if `j' == 2 {
                        local kreg "cumpower_solar_norm_06_14"    
                    }
                    else {
                        local kreg "cumpower_solar_norm_18_22"    
                    }    
                    local iv "inter_solar_above_1"            
                    local labtitle "interaction"            
                }
                else {
                    if `j' == 1 {
                        local kreg "cumpower_solar_norm_06_22"
                    }
                    else if `j' == 2 {
                        local kreg "cumpower_solar_norm_06_14"    
                    }
                    else {
                        local kreg "cumpower_solar_norm_18_22"    
                    }    
                    local iv "inter_solar_above_1 com_pv_potential com_sensitivity_solar_1"            
                    local labtitle "envsust_solar_pot_inter"            
                }            
                
                
    
                local labels_kreg ""
                foreach l of local kreg {
                    local lab : variable label `l'
                    local labels_kreg `" `labels_kreg' "`lab'" "'
                }
                local lab2 : variable label `x'_00_03
                local labels `" `labels' "`lab2'" "'    
                
                local num_iv: word count `iv'
                
                local num_kreg: word count `kreg'
                
                local predictors = `num_iv'+`num_kreg' - 1 // we take out the constant
                
                matrix est_00_03_1 = J(2,`predictors',.)
                matrix est_04_22_1 = J(2,`predictors',.)
                matrix est_04_22_2 = J(2,`predictors',.)
                matrix est_04_22_3 = J(2,`predictors',.)
                matrix est_04_14_1 = J(2,`predictors',.)
                matrix est_04_14_2 = J(2,`predictors',.)
                matrix est_04_14_3 = J(2,`predictors',.)
                matrix est_16_22_1 = J(2,`predictors',.)
                matrix est_16_22_2 = J(2,`predictors',.)
                matrix est_16_22_3 = J(2,`predictors',.)        
                matrix pv_00_03_1 = J(1,`predictors',.)
                matrix pv_04_22_1 = J(1,`predictors',.)
                matrix pv_04_22_2 = J(1,`predictors',.)
                matrix pv_04_22_3 = J(1,`predictors',.)
                matrix pv_04_14_1 = J(1,`predictors',.)
                matrix pv_04_14_2 = J(1,`predictors',.)
                matrix pv_04_14_3 = J(1,`predictors',.)
                matrix pv_16_22_1 = J(1,`predictors',.)
                matrix pv_16_22_2 = J(1,`predictors',.)
                matrix pv_16_22_3 = J(1,`predictors',.)
                
                
        *****************************************************
        * 4. First stage regressions for solar
        *****************************************************        
                
                // First stage regressions
                matrix fs_s_1 = J(2, `predictors', .)
                matrix fs_s_2 = J(2, `predictors', .)
                matrix fs_s_3 = J(2, `predictors', .)
                matrix pv_fs_s_1 = J(1, `predictors', .)
                matrix pv_fs_s_2 = J(1, `predictors', .)
                matrix pv_fs_s_3 = J(1, `predictors', .)
                
                
    
                local labels_iv ""
                foreach l of local iv {
                    local lab : variable label `l'
                    local labels_iv `" `labels_iv' "`lab'" "'    
                }
                foreach var of local kreg {
    
                    log using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/FS_comlevel_solar_`var'_iv`inst'.txt", replace text
                    // No controls
                    reg `var' `iv', r
                    forvalues i = 1 / `predictors' {
                        matrix fs_s_1[1, `i'] = e(b)[1, `i']
                        matrix fs_s_1[2, `i'] = r(table)[2, `i']
                        matrix pv_fs_s_1[1, `i'] = r(table)[4, `i']
                    }
                    reg `var' `iv' `x'_00_03, r
                    forvalues i = 1 / `predictors' {
                        matrix fs_s_2[1, `i'] = e(b)[1, `i']
                        matrix fs_s_2[2, `i'] = r(table)[2, `i']
                        matrix pv_fs_s_2[1, `i'] = r(table)[4, `i']
                    }        
                    // Control for pre-trend and province FE
                    reg `var' `iv' `x'_00_03 i.prov_code, r
                    forvalues i = 1 / `predictors' {
                        matrix fs_s_3[1, `i'] = e(b)[1, `i']
                        matrix fs_s_3[2, `i'] = r(table)[2, `i']
                        matrix pv_fs_s_3[1, `i'] = r(table)[4, `i']
                    }            
                    log close
                }
                matrix colnames fs_s_1 = `labels_iv'
                matrix colnames fs_s_2 = `labels_iv'
                matrix colnames fs_s_3 = `labels_iv'            
                matrix colnames pv_fs_s_1 = `labels_iv'
                matrix colnames pv_fs_s_2 = `labels_iv'
                matrix colnames pv_fs_s_3 = `labels_iv'
            
                
                estadd matrix fs_s_1 = fs_s_1, replace
                estadd matrix fs_s_2 = fs_s_2, replace
                estadd matrix fs_s_3 = fs_s_3, replace    
                estadd matrix pv_fs_s_1 = pv_fs_s_1, replace
                estadd matrix pv_fs_s_2 = pv_fs_s_2, replace
                estadd matrix pv_fs_s_3 = pv_fs_s_3, replace
    
                
                if `j' == 1 {
                    local ivpre1 "\begin{tabularx}{\textwidth}{X c c c}"
                    local ivpre2 "\toprule"
                    local ivpost1 " & \multicolumn{3}{c}{Change in solar} \\"
                    local ivpost2 "\cmidrule(lr){2-4}"
                    local ivpost3 "& (1) & (2) & (3) \\ "
                    local ivpost4 "\midrule "
                    local ivpost5 "\multicolumn{4}{l}{\textit{Panel A. 1st and 2nd wave: 2006-2022}} \\"
                    local ivpost6 "Pre-trend & & \checkmark & \checkmark \\"
                    local ivpost7 "Province FE & & & \checkmark \\"
                    esttab using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/2solar_First_stage_comlevel_`labtitle'.tex", cells("fs_s_1[1](fmt(2) star pvalue(pv_fs_s_1)) fs_s_2[1](fmt(2) star pvalue(pv_fs_s_2)) fs_s_3[1](fmt(2) star pvalue(pv_fs_s_3))" ///
                    "fs_s_1[2](fmt(2) par) fs_s_2[2](fmt(2) par) fs_s_3[2](fmt(2) par)") replace varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
                    collabels(none) prehead("{" "\def\sym#1{\ifmmode^{#1}\else\(^{#1}\)\fi}" "\renewcommand{\arraystretch}{1.2}" "\setlength{\tabcolsep}{6pt}" "`ivpre1'" "`ivpre2'") posthead("`ivpost1'" "`ivpost2'" "`ivpost3'" "`ivpost4'" "`ivpost5'") prefoot("`ivpost6'" "`ivpost7'") postfoot(" \\") substitute("Envir" "Environmental")
                }
                else if `j' == 2 {
                    local ivpost8 "\multicolumn{4}{l}{\textit{Panel B. 1st wave: 2006-2014}} \\"
                    esttab using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/2solar_First_stage_comlevel_`labtitle'.tex", cells("fs_s_1[1](fmt(2) star pvalue(pv_fs_s_1)) fs_s_2[1](fmt(2) star pvalue(pv_fs_s_2)) fs_s_3[1](fmt(2) star pvalue(pv_fs_s_3))" ///
                    "fs_s_1[2](fmt(2) par) fs_s_2[2](fmt(2) par) fs_s_3[2](fmt(2) par)") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
                    collabels(none) prehead("") posthead("`ivpost8'") prefoot("`ivpost6'" "`ivpost7'") postfoot(" \\") substitute("Envir" "Environmental")
                }
                else {
                    local ivpost9 "\multicolumn{4}{l}{\textit{Panel C. 2nd wave: 2018-2022}} \\"
                    esttab using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/2solar_First_stage_comlevel_`labtitle'.tex", cells("fs_s_1[1](fmt(2) star pvalue(pv_fs_s_1)) fs_s_2[1](fmt(2) star pvalue(pv_fs_s_2)) fs_s_3[1](fmt(2) star pvalue(pv_fs_s_3))" ///
                    "fs_s_1[2](fmt(2) par) fs_s_2[2](fmt(2) par) fs_s_3[2](fmt(2) par)") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
                    collabels(none) prehead("") posthead("`ivpost9'") prefoot("`ivpost6'" "`ivpost7'") postfoot("\hline" "\end{tabularx}" "\vspace{0.5em}" "\noindent" "{\footnotesize{\textit{Notes.}} \sym{*} p$<0.10$, \sym{**} p$<0.05$, \sym{***} p$<0.01$}" "}") substitute("Envir" "Environmental")
                }
                
    
        *****************************************************
        * 5. Second stage regressions (2sls) for solar
        *****************************************************        
                
                // Second stage regressions
                
                    
                    // Change 2000-2003
                    ivregress 2sls `x'_00_03 (`kreg' = `iv'), r
                forvalues i = 1 / `predictors' {
                    matrix est_00_03_1[1, `i'] = e(b)[1, `i']
                    matrix est_00_03_1[2, `i'] = r(table)[2, `i']
                    matrix pv_00_03_1[1, `i'] = r(table)[4, `i']
                    
                }
                    
                    // Change 2004-2022, no controls
                forvalues i = 1 / `predictors' {
                    ivregress 2sls `x'_04_22 (`kreg' = `iv'), r
                    matrix est_04_22_1[1, `i'] = e(b)[1, `i']
                    matrix est_04_22_2[2, `i'] = r(table)[2, `i']
                    matrix pv_04_22_1[1, `i']  = r(table)[4, `i']
                    
                }
                
                
                
                    // Change 2004-2022, pre-trend
                    ivregress 2sls `x'_04_22 (`kreg' = `iv') `x'_00_03, r
                forvalues i = 1 / `predictors' {
                    matrix est_04_22_2[1, `i'] = e(b)[1, `i']
                    matrix est_04_22_2[2, `i'] = r(table)[2, `i']
                    matrix pv_04_22_2[1, `i']  = r(table)[4, `i']
                }
                
                    // Change 2004-2022, pre-trend + province FE
                    ivregress 2sls `x'_04_22 (`kreg' = `iv') `x'_00_03 i.prov_code, r
                forvalues i = 1 / `predictors' {
                    matrix est_04_22_3[1, `i'] = e(b)[1, `i']
                    matrix est_04_22_3[2, `i'] = r(table)[2, `i']
                    matrix pv_04_22_3[1, `i']  = r(table)[4, `i']    
                }
                
                    // Change 2004-2014, no controls
                    ivregress 2sls `x'_04_14 (`kreg' = `iv'), r
                forvalues i = 1 / `predictors' {
                    matrix est_04_14_1[1, `i'] = e(b)[1, `i']
                    matrix est_04_14_1[2, `i'] = r(table)[2, `i']
                    matrix pv_04_14_1[1, `i']  = r(table)[4, `i']    
                }
                
                    // Change 2004-2014, pre-trend
                    ivregress 2sls `x'_04_14 (`kreg' = `iv') `x'_00_03, r
                forvalues i = 1 / `predictors' {
                    matrix est_04_14_2[1, `i'] = e(b)[1, `i']
                    matrix est_04_14_2[2, `i'] = r(table)[2, `i']
                    matrix pv_04_14_2[1, `i']  = r(table)[4, `i']    
                }
                
                    // Change 2004-2014, pre-trend + province FE
                    ivregress 2sls `x'_04_14 (`kreg' = `iv') `x'_00_03 i.prov_code, r
                forvalues i = 1 / `predictors' {
                    matrix est_04_14_3[1, `i'] = e(b)[1, `i']
                    matrix est_04_14_3[2, `i'] = r(table)[2, `i']
                    matrix pv_04_14_3[1, `i']  = r(table)[4, `i']    
                    
                }
                
                    // Change 2016-2022, no controls
                    ivregress 2sls `x'_16_22 (`kreg' = `iv'), r
                forvalues i = 1 / `predictors' {
                    matrix est_16_22_1[1, `i'] = e(b)[1, `i']
                    matrix est_16_22_1[2, `i'] = r(table)[2, `i']
                    matrix pv_16_22_1[1, `i']  = r(table)[4, `i']    
                }
                
                    // Change 2016-2022, pre-trend
                    ivregress 2sls `x'_16_22 (`kreg' = `iv') `x'_00_03, r
                forvalues i = 1 / `predictors' {
                    matrix est_16_22_2[1, `i'] = e(b)[1, `i']
                    matrix est_16_22_2[2, `i'] = r(table)[2, `i']
                    matrix pv_16_22_2[1, `i']  = r(table)[4, `i']    
                }
                
                    // Change 2016-2022, pre-trend + province FE
                    ivregress 2sls `x'_16_22 (`kreg' = `iv') `x'_00_03 i.prov_code, r
                forvalues i = 1 / `predictors' {
                    matrix est_16_22_3[1, `i'] = e(b)[1, `i']
                    matrix est_16_22_3[2, `i'] = r(table)[2, `i']
                    matrix pv_16_22_3[1, `i']  = r(table)[4, `i']    
                }    
                        
                matrix colnames est_00_03_1 = `labels_kreg'
                matrix colnames est_04_22_1 = `labels_kreg'
                matrix colnames est_04_22_2 = `labels_kreg'
                matrix colnames est_04_22_3 = `labels_kreg'    
                matrix colnames est_04_14_1 = `labels_kreg'
                matrix colnames est_04_14_2 = `labels_kreg'
                matrix colnames est_04_14_3 = `labels_kreg'
                matrix colnames est_16_22_1 = `labels_kreg'
                matrix colnames est_16_22_2 = `labels_kreg'
                matrix colnames est_16_22_3 = `labels_kreg'
                matrix colnames pv_00_03_1 = `labels_kreg'
                matrix colnames pv_04_22_1 = `labels_kreg'
                matrix colnames pv_04_22_2 = `labels_kreg'
                matrix colnames pv_04_22_3 = `labels_kreg'
                matrix colnames pv_04_14_1 = `labels_kreg'
                matrix colnames pv_04_14_2 = `labels_kreg'
                matrix colnames pv_04_14_3 = `labels_kreg'
                matrix colnames pv_16_22_1 = `labels_kreg'
                matrix colnames pv_16_22_2 = `labels_kreg'
                matrix colnames pv_16_22_3 = `labels_kreg'        
                
                estadd matrix est_00_03_1 = est_00_03_1, replace
                estadd matrix est_04_22_1 = est_04_22_1, replace
                estadd matrix est_04_22_2 = est_04_22_2, replace
                estadd matrix est_04_22_3 = est_04_22_3, replace                
                estadd matrix est_04_14_1 = est_04_14_1, replace
                estadd matrix est_04_14_2 = est_04_14_2, replace
                estadd matrix est_04_14_3 = est_04_14_3, replace
                estadd matrix est_16_22_1 = est_16_22_1, replace
                estadd matrix est_16_22_2 = est_16_22_2, replace
                estadd matrix est_16_22_3 = est_16_22_3, replace
                estadd matrix pv_00_03_1 = pv_00_03_1, replace
                estadd matrix pv_04_22_1 = pv_04_22_1, replace
                estadd matrix pv_04_22_2 = pv_04_22_2, replace
                estadd matrix pv_04_22_3 = pv_04_22_3, replace        
                estadd matrix pv_04_14_1 = pv_04_14_1, replace
                estadd matrix pv_04_14_2 = pv_04_14_2, replace
                estadd matrix pv_04_14_3 = pv_04_14_3, replace
                estadd matrix pv_16_22_1 = pv_16_22_1, replace
                estadd matrix pv_16_22_2 = pv_16_22_2, replace
                estadd matrix pv_16_22_3 = pv_16_22_3, replace    
                
    
                        
    
                // Output        
                if `j' == 1 {
                    local pre1 "\begin{tabularx}{\linewidth}{p{5cm}cp{0.5cm}p{2cm}p{2cm}p{2cm}p{0.5cm}p{2cm}p{2cm}p{2cm}p{0.5cm}p{2cm}p{2cm}p{2cm}}"
                    local pre2 "\hline"
                    local post1 "`title' & 2000-2003 & & \multicolumn{3}{c}{2004-2022} & & \multicolumn{3}{c}{2004-2014} & & \multicolumn{3}{c}{2016-2022} \\"
                    local post2 "\cline{2-2} \cline{4-6} \cline{8-10} \cline{12-14}"
                    local post3 "& (1) & & (2) & (3) & (4) & & (5) & (6) & (7) & & (8) & (9) & (10) \\ \hline"    
                    local post4 "\multicolumn{14}{l}{\textit{Panel A. 1st and 2nd wave: 2006-2022}} \\"
                    local post5 "Province FE & & & & & \checkmark & & & & & & & & \\"
                    esttab using "AM/Estimates/Tables/Long_term_effects/IV/2lte_solar_IV_comlevel_`x'_`labtitle'.tex", cells("est_00_03_1[1](fmt(2) star pvalue(pv_00_03_1)) . est_04_22_1[1](fmt(2) star pvalue(pv_04_22_1)) est_04_22_2[1](fmt(2) star pvalue(pv_04_22_2)) est_04_22_3[1](fmt(2) star pvalue(pv_04_22_3)) . . . . . . . ." ///
                    "est_00_03_1[2](fmt(2) par) . est_04_22_1[2](fmt(2) par) est_04_22_2[2](fmt(2) par) est_04_22_3[2](fmt(2) par) . . . . . . . .") replace varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
                    collabels(none) prehead("{" "\def\sym#1{\ifmmode^{#1}\else\(^{#1}\)\fi}" "`pre1'" "`pre2'") posthead("`post1'" "`post2'" "`post3'" "`post4'") prefoot("`post5'") postfoot(" \\") substitute("AAA" "06-22" " . " " " " (.) " " ")        
                }
                else if `j' == 2 {
                    local post6 "\multicolumn{14}{l}{\textit{Panel B. 1st wave: 2006-2014}} \\"
                    local post7 "Province FE & & & & & & & & & \checkmark & & & & \\"
                    esttab using "AM/Estimates/Tables/Long_term_effects/IV/2lte_solar_IV_comlevel_`x'_`labtitle'.tex", cells("est_00_03_1[1](fmt(2) star pvalue(pv_00_03_1)) . . . . . est_04_14_1[1](fmt(2) star pvalue(pv_04_14_1)) est_04_14_2[1](fmt(2) star pvalue(pv_04_14_2)) est_04_14_3[1](fmt(2) star pvalue(pv_04_14_3)) . . . ." ///
                    "est_00_03_1[2](fmt(2) par) . . . . . est_04_14_1[2](fmt(2) par) est_04_14_2[2](fmt(2) par) est_04_14_3[2](fmt(2) par) . . . .") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
                    collabels(none) prehead("") posthead("`post6'") prefoot("`post7'")  postfoot(" \\") substitute("BBB" "06-14" " . " " " " (.) " " ")        
                }        
                else {
                    local post8 "\multicolumn{14}{l}{\textit{Panel C. 2nd wave: 2018-2022}} \\"    
                    local post9 "Province FE & & & & & & & & & & & & & \checkmark \\"
                    esttab using "AM/Estimates/Tables/Long_term_effects/IV/2lte_solar_IV_comlevel_`x'_`labtitle'.tex", cells("est_00_03_1[1](fmt(2) star pvalue(pv_00_03_1)) . . . . . . . . . est_16_22_1[1](fmt(2) star pvalue(pv_16_22_1)) est_16_22_2[1](fmt(2) star pvalue(pv_16_22_2)) est_16_22_3[1](fmt(2) star pvalue(pv_16_22_3))" ///
                    "est_00_03_1[2](fmt(2) par) . . . . . . . . . est_16_22_1[2](fmt(2) par) est_16_22_2[2](fmt(2) par) est_16_22_3[2](fmt(2) par)") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
                    collabels(none) prehead("") posthead("`post8'") prefoot("`post9'") postfoot("\hline" "\end{tabularx}" "}")    substitute("CCC" "18-22" " . " " " " (.) " " ")                
                
                }
            }            
        }
        
    }

  • #2
    I changed the 2cm column widths to 1cm, and compiled on Overleaf with
    Code:
    \documentclass{article}
    \usepackage[papersize={26cm,10cm},left=1cm,right=1cm,top=1cm,bottom=2cm]{geometry}
    \usepackage{tabularx,booktabs,dingbat}
    \begin{document}
    %\include{2solar_First_stage_comlevel_envsustain_above_one}
    \include{2lte_solar_IV_comlevel_pop_envsustain_above_one}
    \end{document}
    The result is:
    Click image for larger version

Name:	2lte_solar_IV_comlevel_pop_envsustain_above_one.png
Views:	1
Size:	76.6 KB
ID:	1769702



    Does it look the same for you? You say "the table is not what you would expect". So that we can focus our attention, what about this table is unexpected?
    Last edited by Nils Enevoldsen; 18 Dec 2024, 14:25.

    Comment


    • #3
      Hello,

      Thank you for your help and sorry, I don't specify the problem in detail. Also, thank you for the code provided for LaTeX, I had trouble fitting the table perfectly into a page. Thank you!

      I also realise that I don't have the labels attributed in post#1, sorry about that. Here they are:

      Code:
      * label variables
      label var com_sensitivity_solar "Envir sustainability solar"
      label var com_sensitivity_wind "Envir sustainability wind"
      label var com_sensitivity_solar_1 "Sustainability solar $>1$"
      label var com_sensitivity_wind_1 "Sustainability wind $>1$"
      label var com_pv_potential "Solar potential"
      label var com_wind_power_dens "Wind potential"
      label var inter_solar "Sustainaibility*potential, solar"
      label var inter_wind "Sustainaibility*potential, wind"
      label var inter_solar_above_1 "Inter. Sustain. ($>1$) x Solar P."
      label var inter_wind_above_1 "Inter. Sustain. ($>1$) x Wind P."
      
      label var cumpower_solar_norm_06_22 "Change in solar, AAA"
      label var cumpower_wind_norm_06_22 "Change in wind, AAA"
      label var cumpower_solar_norm_06_14 "Change in solar, BBB"
      label var cumpower_wind_norm_06_14 "Change in wind, BBB"    
      label var cumpower_solar_norm_18_22 "Change in solar, CCC"
      label var cumpower_wind_norm_18_22 "Change in wind, CCC"    
      
      label var pop_00_03 "Population pretrend, 00-03"
      Basically, when I run the second-stage regression, I would like that the pop_00_03 variable appears for all regression, like the enclosed table (the "Change in wind" should not appear, as I am explicitly separating the regressions):
      Click image for larger version

Name:	Example_table.png
Views:	1
Size:	55.4 KB
ID:	1769731



      It seems that in my loop I don't seem to be capturing this variable, and I don't know why. The idea would be to include this variable and these coefficients, standard errors and p-value.
      I do not know if it is related to my definition of the local here:

      Code:
                  local num_iv: word count `iv'
                  
                  local num_kreg: word count `kreg'
                  
                  local predictors = `num_iv'+`num_kreg' - 1 // we take out the constant
      Thank you very much for your help on this matter.
      Last edited by Michael Duarte Goncalves; 19 Dec 2024, 02:19.

      Comment


      • #4
        Hi again,

        I am dealing with another problem when I use `inst = 4'. The loop repeats some variables three times for each wave. Please take a look at the enclosed screen shot. I don't know how to solve this problem.
        That variable should only appear once and the pre-trend for population 00-03 should also be there.


        Click image for larger version

Name:	Example_table2.png
Views:	1
Size:	33.8 KB
ID:	1769738



        Could you please give me some hints about that?

        Thank you so much.
        Michael

        Comment


        • #5
          Okay, try this out.
          1. Changed definition of local labels
          2. Changed definition of local predictors and defined local predictors_alt
          3. When storing estimates, sometimes use predictors and sometimes use predictors_alt
          4. Fix one typo where est_04_22_2 should be est_04_22_1
          5. Use local labels instead of local labels_kreg to set colnames
          Click image for larger version

Name:	2lte_solar_IV_comlevel_pop_envsustain_above_one_modified.png
Views:	1
Size:	114.1 KB
ID:	1769765

          Code:
          *****************************************************
          * 2. Define some macros for further reg and 2sls
          *****************************************************
          local inst = 1 // = 1 use environmental sustainability index above one as instrument
          // = 2 use solar/wind potential
          // = 3 use interaction
          // = 4 use 1; 2 & 3 together
          local energy = 1 // = 1 if solar
          // = 2 if wind
          // Estimation
          *local vlist "logpop pop immig_flow emig_flow births"
          local vlist "pop"
          foreach x of local vlist {
          if "`x'" == "pop" {
          local title "Change in population"
          }
          else if "`x'" == "logpop" {
          local title "Log change in population"
          }
          else if "`x'" == "immig_flow" {
          local title "In-migrations (cumulative over)"
          }
          else if "`x'" == "emig_flow" {
          local title "Out-migrations (cumulative over)"
          }
          else {
          local title "Births (cumulative over)"
          }
          *****************************************************
          * 3. We focus here on solar (`energy' = 1)
          *****************************************************
          
          if `energy' == 1 {
          eststo clear
          forvalues j = 1 / 3 {
          if `inst' == 1 {
          if `j' == 1 {
          local kreg "cumpower_solar_norm_06_22"
          }
          else if `j' == 2 {
          local kreg "cumpower_solar_norm_06_14"
          }
          else {
          local kreg "cumpower_solar_norm_18_22"
          }
          local iv "com_sensitivity_solar_1"
          local labtitle "envsustain_above_one"
          }
          else if `inst' == 2 {
          if `j' == 1 {
          local kreg "cumpower_solar_norm_06_22"
          }
          else if `j' == 2 {
          local kreg "cumpower_solar_norm_06_14"
          }
          else {
          local kreg "cumpower_solar_norm_18_22"
          }
          local iv "com_pv_potential"
          local labtitle "solar_potential"
          }
          else if `inst' == 3 {
          if `j' == 1 {
          local kreg "cumpower_solar_norm_06_22"
          }
          else if `j' == 2 {
          local kreg "cumpower_solar_norm_06_14"
          }
          else {
          local kreg "cumpower_solar_norm_18_22"
          }
          local iv "inter_solar_above_1"
          local labtitle "interaction"
          }
          else {
          if `j' == 1 {
          local kreg "cumpower_solar_norm_06_22"
          }
          else if `j' == 2 {
          local kreg "cumpower_solar_norm_06_14"
          }
          else {
          local kreg "cumpower_solar_norm_18_22"
          }
          local iv "inter_solar_above_1 com_pv_potential com_sensitivity_solar_1"
          local labtitle "envsust_solar_pot_inter"
          }
          local labels_kreg ""
          foreach l of local kreg {
          local lab : variable label `l'
          local labels_kreg `" `labels_kreg' "`lab'" "'
          }
          local lab2 : variable label `x'_00_03
          local labels `" `labels' "`lab2'" "'
          local num_iv: word count `iv'
          local num_kreg: word count `kreg'
          local predictors = `num_iv'+`num_kreg' - 1 // we take out the constant
          matrix est_00_03_1 = J(2,`predictors',.)
          matrix est_04_22_1 = J(2,`predictors',.)
          matrix est_04_22_2 = J(2,`predictors',.)
          matrix est_04_22_3 = J(2,`predictors',.)
          matrix est_04_14_1 = J(2,`predictors',.)
          matrix est_04_14_2 = J(2,`predictors',.)
          matrix est_04_14_3 = J(2,`predictors',.)
          matrix est_16_22_1 = J(2,`predictors',.)
          matrix est_16_22_2 = J(2,`predictors',.)
          matrix est_16_22_3 = J(2,`predictors',.)
          matrix pv_00_03_1 = J(1,`predictors',.)
          matrix pv_04_22_1 = J(1,`predictors',.)
          matrix pv_04_22_2 = J(1,`predictors',.)
          matrix pv_04_22_3 = J(1,`predictors',.)
          matrix pv_04_14_1 = J(1,`predictors',.)
          matrix pv_04_14_2 = J(1,`predictors',.)
          matrix pv_04_14_3 = J(1,`predictors',.)
          matrix pv_16_22_1 = J(1,`predictors',.)
          matrix pv_16_22_2 = J(1,`predictors',.)
          matrix pv_16_22_3 = J(1,`predictors',.)
          *****************************************************
          * 4. First stage regressions for solar
          *****************************************************
          // First stage regressions
          matrix fs_s_1 = J(2, `predictors', .)
          matrix fs_s_2 = J(2, `predictors', .)
          matrix fs_s_3 = J(2, `predictors', .)
          matrix pv_fs_s_1 = J(1, `predictors', .)
          matrix pv_fs_s_2 = J(1, `predictors', .)
          matrix pv_fs_s_3 = J(1, `predictors', .)
          local labels_iv ""
          foreach l of local iv {
          local lab : variable label `l'
          local labels_iv `" `labels_iv' "`lab'" "'
          }
          foreach var of local kreg {
          log using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/FS_comlevel_solar_`var'_iv`inst'.txt", replace text
          // No controls
          reg `var' `iv', r
          forvalues i = 1 / `predictors' {
          matrix fs_s_1[1, `i'] = e(b)[1, `i']
          matrix fs_s_1[2, `i'] = r(table)[2, `i']
          matrix pv_fs_s_1[1, `i'] = r(table)[4, `i']
          }
          reg `var' `iv' `x'_00_03, r
          forvalues i = 1 / `predictors' {
          matrix fs_s_2[1, `i'] = e(b)[1, `i']
          matrix fs_s_2[2, `i'] = r(table)[2, `i']
          matrix pv_fs_s_2[1, `i'] = r(table)[4, `i']
          }
          // Control for pre-trend and province FE
          reg `var' `iv' `x'_00_03 i.prov_code, r
          forvalues i = 1 / `predictors' {
          matrix fs_s_3[1, `i'] = e(b)[1, `i']
          matrix fs_s_3[2, `i'] = r(table)[2, `i']
          matrix pv_fs_s_3[1, `i'] = r(table)[4, `i']
          }
          log close
          }
          matrix colnames fs_s_1 = `labels_iv'
          matrix colnames fs_s_2 = `labels_iv'
          matrix colnames fs_s_3 = `labels_iv'
          matrix colnames pv_fs_s_1 = `labels_iv'
          matrix colnames pv_fs_s_2 = `labels_iv'
          matrix colnames pv_fs_s_3 = `labels_iv'
          estadd matrix fs_s_1 = fs_s_1, replace
          estadd matrix fs_s_2 = fs_s_2, replace
          estadd matrix fs_s_3 = fs_s_3, replace
          estadd matrix pv_fs_s_1 = pv_fs_s_1, replace
          estadd matrix pv_fs_s_2 = pv_fs_s_2, replace
          estadd matrix pv_fs_s_3 = pv_fs_s_3, replace
          if `j' == 1 {
          local ivpre1 "\begin{tabularx}{\textwidth}{X c c c}"
          local ivpre2 "\toprule"
          local ivpost1 " & \multicolumn{3}{c}{Change in solar} \\"
          local ivpost2 "\cmidrule(lr){2-4}"
          local ivpost3 "& (1) & (2) & (3) \\ "
          local ivpost4 "\midrule "
          local ivpost5 "\multicolumn{4}{l}{\textit{Panel A. 1st and 2nd wave: 2006-2022}} \\"
          local ivpost6 "Pre-trend & & \checkmark & \checkmark \\"
          local ivpost7 "Province FE & & & \checkmark \\"
          esttab using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/2solar_First_stage_comlevel_`labtitle'.tex", cells("fs_s_1[1](fmt(2) star pvalue(pv_fs_s_1)) fs_s_2[1](fmt(2) star pvalue(pv_fs_s_2)) fs_s_3[1](fmt(2) star pvalue(pv_fs_s_3))" ///
          "fs_s_1[2](fmt(2) par) fs_s_2[2](fmt(2) par) fs_s_3[2](fmt(2) par)") replace varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
          collabels(none) prehead("{" "\def\sym#1{\ifmmode^{#1}\else\(^{#1}\)\fi}" "\renewcommand{\arraystretch}{1.2}" "\setlength{\tabcolsep}{6pt}" "`ivpre1'" "`ivpre2'") posthead("`ivpost1'" "`ivpost2'" "`ivpost3'" "`ivpost4'" "`ivpost5'") prefoot("`ivpost6'" "`ivpost7'") postfoot(" \\") substitute("Envir" "Environmental")
          }
          else if `j' == 2 {
          local ivpost8 "\multicolumn{4}{l}{\textit{Panel B. 1st wave: 2006-2014}} \\"
          esttab using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/2solar_First_stage_comlevel_`labtitle'.tex", cells("fs_s_1[1](fmt(2) star pvalue(pv_fs_s_1)) fs_s_2[1](fmt(2) star pvalue(pv_fs_s_2)) fs_s_3[1](fmt(2) star pvalue(pv_fs_s_3))" ///
          "fs_s_1[2](fmt(2) par) fs_s_2[2](fmt(2) par) fs_s_3[2](fmt(2) par)") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
          collabels(none) prehead("") posthead("`ivpost8'") prefoot("`ivpost6'" "`ivpost7'") postfoot(" \\") substitute("Envir" "Environmental")
          }
          else {
          local ivpost9 "\multicolumn{4}{l}{\textit{Panel C. 2nd wave: 2018-2022}} \\"
          esttab using "AM/Estimates/Tables/Long_term_effects/IV/First_stage/2solar_First_stage_comlevel_`labtitle'.tex", cells("fs_s_1[1](fmt(2) star pvalue(pv_fs_s_1)) fs_s_2[1](fmt(2) star pvalue(pv_fs_s_2)) fs_s_3[1](fmt(2) star pvalue(pv_fs_s_3))" ///
          "fs_s_1[2](fmt(2) par) fs_s_2[2](fmt(2) par) fs_s_3[2](fmt(2) par)") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
          collabels(none) prehead("") posthead("`ivpost9'") prefoot("`ivpost6'" "`ivpost7'") postfoot("\hline" "\end{tabularx}" "\vspace{0.5em}" "\noindent" "{\footnotesize{\textit{Notes.}} \sym{*} p$<0.10$, \sym{**} p$<0.05$, \sym{***} p$<0.01$}" "}") substitute("Envir" "Environmental")
          }
          *****************************************************
          * 5. Second stage regressions (2sls) for solar
          *****************************************************
          // Second stage regressions
          // Change 2000-2003
          ivregress 2sls `x'_00_03 (`kreg' = `iv'), r
          forvalues i = 1 / `predictors' {
          matrix est_00_03_1[1, `i'] = e(b)[1, `i']
          matrix est_00_03_1[2, `i'] = r(table)[2, `i']
          matrix pv_00_03_1[1, `i'] = r(table)[4, `i']
          }
          // Change 2004-2022, no controls
          forvalues i = 1 / `predictors' {
          ivregress 2sls `x'_04_22 (`kreg' = `iv'), r
          matrix est_04_22_1[1, `i'] = e(b)[1, `i']
          matrix est_04_22_2[2, `i'] = r(table)[2, `i']
          matrix pv_04_22_1[1, `i'] = r(table)[4, `i']
          }
          // Change 2004-2022, pre-trend
          ivregress 2sls `x'_04_22 (`kreg' = `iv') `x'_00_03, r
          forvalues i = 1 / `predictors' {
          matrix est_04_22_2[1, `i'] = e(b)[1, `i']
          matrix est_04_22_2[2, `i'] = r(table)[2, `i']
          matrix pv_04_22_2[1, `i'] = r(table)[4, `i']
          }
          // Change 2004-2022, pre-trend + province FE
          ivregress 2sls `x'_04_22 (`kreg' = `iv') `x'_00_03 i.prov_code, r
          forvalues i = 1 / `predictors' {
          matrix est_04_22_3[1, `i'] = e(b)[1, `i']
          matrix est_04_22_3[2, `i'] = r(table)[2, `i']
          matrix pv_04_22_3[1, `i'] = r(table)[4, `i']
          }
          // Change 2004-2014, no controls
          ivregress 2sls `x'_04_14 (`kreg' = `iv'), r
          forvalues i = 1 / `predictors' {
          matrix est_04_14_1[1, `i'] = e(b)[1, `i']
          matrix est_04_14_1[2, `i'] = r(table)[2, `i']
          matrix pv_04_14_1[1, `i'] = r(table)[4, `i']
          }
          // Change 2004-2014, pre-trend
          ivregress 2sls `x'_04_14 (`kreg' = `iv') `x'_00_03, r
          forvalues i = 1 / `predictors' {
          matrix est_04_14_2[1, `i'] = e(b)[1, `i']
          matrix est_04_14_2[2, `i'] = r(table)[2, `i']
          matrix pv_04_14_2[1, `i'] = r(table)[4, `i']
          }
          // Change 2004-2014, pre-trend + province FE
          ivregress 2sls `x'_04_14 (`kreg' = `iv') `x'_00_03 i.prov_code, r
          forvalues i = 1 / `predictors' {
          matrix est_04_14_3[1, `i'] = e(b)[1, `i']
          matrix est_04_14_3[2, `i'] = r(table)[2, `i']
          matrix pv_04_14_3[1, `i'] = r(table)[4, `i']
          }
          // Change 2016-2022, no controls
          ivregress 2sls `x'_16_22 (`kreg' = `iv'), r
          forvalues i = 1 / `predictors' {
          matrix est_16_22_1[1, `i'] = e(b)[1, `i']
          matrix est_16_22_1[2, `i'] = r(table)[2, `i']
          matrix pv_16_22_1[1, `i'] = r(table)[4, `i']
          }
          // Change 2016-2022, pre-trend
          ivregress 2sls `x'_16_22 (`kreg' = `iv') `x'_00_03, r
          forvalues i = 1 / `predictors' {
          matrix est_16_22_2[1, `i'] = e(b)[1, `i']
          matrix est_16_22_2[2, `i'] = r(table)[2, `i']
          matrix pv_16_22_2[1, `i'] = r(table)[4, `i']
          }
          // Change 2016-2022, pre-trend + province FE
          ivregress 2sls `x'_16_22 (`kreg' = `iv') `x'_00_03 i.prov_code, r
          forvalues i = 1 / `predictors' {
          matrix est_16_22_3[1, `i'] = e(b)[1, `i']
          matrix est_16_22_3[2, `i'] = r(table)[2, `i']
          matrix pv_16_22_3[1, `i'] = r(table)[4, `i']
          }
          matrix colnames est_00_03_1 = `labels_kreg'
          matrix colnames est_04_22_1 = `labels_kreg'
          matrix colnames est_04_22_2 = `labels_kreg'
          matrix colnames est_04_22_3 = `labels_kreg'
          matrix colnames est_04_14_1 = `labels_kreg'
          matrix colnames est_04_14_2 = `labels_kreg'
          matrix colnames est_04_14_3 = `labels_kreg'
          matrix colnames est_16_22_1 = `labels_kreg'
          matrix colnames est_16_22_2 = `labels_kreg'
          matrix colnames est_16_22_3 = `labels_kreg'
          matrix colnames pv_00_03_1 = `labels_kreg'
          matrix colnames pv_04_22_1 = `labels_kreg'
          matrix colnames pv_04_22_2 = `labels_kreg'
          matrix colnames pv_04_22_3 = `labels_kreg'
          matrix colnames pv_04_14_1 = `labels_kreg'
          matrix colnames pv_04_14_2 = `labels_kreg'
          matrix colnames pv_04_14_3 = `labels_kreg'
          matrix colnames pv_16_22_1 = `labels_kreg'
          matrix colnames pv_16_22_2 = `labels_kreg'
          matrix colnames pv_16_22_3 = `labels_kreg'
          estadd matrix est_00_03_1 = est_00_03_1, replace
          estadd matrix est_04_22_1 = est_04_22_1, replace
          estadd matrix est_04_22_2 = est_04_22_2, replace
          estadd matrix est_04_22_3 = est_04_22_3, replace
          estadd matrix est_04_14_1 = est_04_14_1, replace
          estadd matrix est_04_14_2 = est_04_14_2, replace
          estadd matrix est_04_14_3 = est_04_14_3, replace
          estadd matrix est_16_22_1 = est_16_22_1, replace
          estadd matrix est_16_22_2 = est_16_22_2, replace
          estadd matrix est_16_22_3 = est_16_22_3, replace
          estadd matrix pv_00_03_1 = pv_00_03_1, replace
          estadd matrix pv_04_22_1 = pv_04_22_1, replace
          estadd matrix pv_04_22_2 = pv_04_22_2, replace
          estadd matrix pv_04_22_3 = pv_04_22_3, replace
          estadd matrix pv_04_14_1 = pv_04_14_1, replace
          estadd matrix pv_04_14_2 = pv_04_14_2, replace
          estadd matrix pv_04_14_3 = pv_04_14_3, replace
          estadd matrix pv_16_22_1 = pv_16_22_1, replace
          estadd matrix pv_16_22_2 = pv_16_22_2, replace
          estadd matrix pv_16_22_3 = pv_16_22_3, replace
          
          // Output
          if `j' == 1 {
          local pre1 "\begin{tabularx}{\linewidth}{p{5cm}cp{0.5cm}p{2cm}p{2cm}p{2cm}p{0.5cm}p{2cm}p{2cm}p{2cm}p{0.5cm}p{2cm}p{2cm}p{2cm}}"
          local pre2 "\hline"
          local post1 "`title' & 2000-2003 & & \multicolumn{3}{c}{2004-2022} & & \multicolumn{3}{c}{2004-2014} & & \multicolumn{3}{c}{2016-2022} \\"
          local post2 "\cline{2-2} \cline{4-6} \cline{8-10} \cline{12-14}"
          local post3 "& (1) & & (2) & (3) & (4) & & (5) & (6) & (7) & & (8) & (9) & (10) \\ \hline"
          local post4 "\multicolumn{14}{l}{\textit{Panel A. 1st and 2nd wave: 2006-2022}} \\"
          local post5 "Province FE & & & & & \checkmark & & & & & & & & \\"
          esttab using "AM/Estimates/Tables/Long_term_effects/IV/2lte_solar_IV_comlevel_`x'_`labtitle'.tex", cells("est_00_03_1[1](fmt(2) star pvalue(pv_00_03_1)) . est_04_22_1[1](fmt(2) star pvalue(pv_04_22_1)) est_04_22_2[1](fmt(2) star pvalue(pv_04_22_2)) est_04_22_3[1](fmt(2) star pvalue(pv_04_22_3)) . . . . . . . ." ///
          "est_00_03_1[2](fmt(2) par) . est_04_22_1[2](fmt(2) par) est_04_22_2[2](fmt(2) par) est_04_22_3[2](fmt(2) par) . . . . . . . .") replace varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
          collabels(none) prehead("{" "\def\sym#1{\ifmmode^{#1}\else\(^{#1}\)\fi}" "`pre1'" "`pre2'") posthead("`post1'" "`post2'" "`post3'" "`post4'") prefoot("`post5'") postfoot(" \\") substitute("AAA" "06-22" " . " " " " (.) " " ")
          }
          else if `j' == 2 {
          local post6 "\multicolumn{14}{l}{\textit{Panel B. 1st wave: 2006-2014}} \\"
          local post7 "Province FE & & & & & & & & & \checkmark & & & & \\"
          esttab using "AM/Estimates/Tables/Long_term_effects/IV/2lte_solar_IV_comlevel_`x'_`labtitle'.tex", cells("est_00_03_1[1](fmt(2) star pvalue(pv_00_03_1)) . . . . . est_04_14_1[1](fmt(2) star pvalue(pv_04_14_1)) est_04_14_2[1](fmt(2) star pvalue(pv_04_14_2)) est_04_14_3[1](fmt(2) star pvalue(pv_04_14_3)) . . . ." ///
          "est_00_03_1[2](fmt(2) par) . . . . . est_04_14_1[2](fmt(2) par) est_04_14_2[2](fmt(2) par) est_04_14_3[2](fmt(2) par) . . . .") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
          collabels(none) prehead("") posthead("`post6'") prefoot("`post7'") postfoot(" \\") substitute("BBB" "06-14" " . " " " " (.) " " ")
          }
          else {
          local post8 "\multicolumn{14}{l}{\textit{Panel C. 2nd wave: 2018-2022}} \\"
          local post9 "Province FE & & & & & & & & & & & & & \checkmark \\"
          esttab using "AM/Estimates/Tables/Long_term_effects/IV/2lte_solar_IV_comlevel_`x'_`labtitle'.tex", cells("est_00_03_1[1](fmt(2) star pvalue(pv_00_03_1)) . . . . . . . . . est_16_22_1[1](fmt(2) star pvalue(pv_16_22_1)) est_16_22_2[1](fmt(2) star pvalue(pv_16_22_2)) est_16_22_3[1](fmt(2) star pvalue(pv_16_22_3))" ///
          "est_00_03_1[2](fmt(2) par) . . . . . . . . . est_16_22_1[2](fmt(2) par) est_16_22_2[2](fmt(2) par) est_16_22_3[2](fmt(2) par)") append varwidth(40) starlevels(* 0.10 ** 0.05 *** 0.01) noobs nodepvars nonumbers nomtitles nolines ///
          collabels(none) prehead("") posthead("`post8'") prefoot("`post9'") postfoot("\hline" "\end{tabularx}" "}") substitute("CCC" "18-22" " . " " " " (.) " " ")
          }
          }
          }
          }

          Comment


          • #6
            I hope you will forgive me if I don't tackle the follow-up question. While I am sympathetic, this code is, um, a little bit thorny. I tried for some time to identify the "magic switch" that would make this code operate as intended, but I didn't find it. In your follow up question, the issue is that those (mislabeled) coefficients are actually the IV coefficients. But I don't immediately see how the esttab code is "supposed" to skip them. Another Statalist user with a higher pain tolerance may be able to help.

            One last caution -- I am always leery of code that manually sets labels like this. It is all too easy to accidentally have an off-by-one error and end up labeling a coefficient with an entirely different label. I strongly suggest doing rationality checks with the results-window ivregress output to make sure the coefficients are being labeled correctly in the LaTeX output.

            Comment


            • #7
              I agree with Nils Enevoldsen, the code is difficult to work with. By all accounts I have a very high pain tolerance for code like this. I started working through it shortly after you posted. Some of the complexity here is necessary from what I can tell, but some of the calculations here aren't even necessary to produce the table at the end. It looks like we are just spending cycles producing regressions we never use just to "simplify" the process.

              It seems to me the original author had grand plans in mind for this piece of code, with lots of generalizability. Much of that generalizability is not realized in this implementation, which is why we loop through a list of one variable (pop) at the beginning, and why we check to see if energy == 1, even though the code does not allow for any other options in practice. If I were speaking to the original author, I'd probably want to let them know its usually easier to code for the specific case and generalize from there rather than the other way around.

              Michael Duarte Goncalves how open would you be to a complete rewrite? I was working on one the other day that uses -collect- and tables instead of matrixes to generate similar results, but didn't quite finish. I might have another opportunity to take a look sometime in the next few days, but I won't bother if you need a small modification to this code instead for some reason.

              Comment


              • #8
                Hello,

                Nils Enevoldsen : Thank you very much Nils for your help. By making the changes you suggest everything now runs like clockwork. Of course I forgive you: the code was very difficult for me to understand from the very first moment!

                As for the second question I asked you in post #4, I managed to solve the problem by following your advice. Thank you. It's true that the coefficients were incorrectly labelled.

                Finally, thank you very much for your time!


                Daniel Schaefer: Oh yes, of course! I'm more than open to improving the code, even if it's not my own. It's highly likely that I'll need this code again, and in a more general context (with, for example, `energy‘ = 1,.., 15, or `inst’ = 1,...,10. So an upgrade wouldn't hurt at all. Many thanks!

                Especially as I want to become as good a programmer as you, Nils, and so many other people who help me on Statalist and I admire.


                Thank you both for your advices.

                Comment


                • #9
                  Hello again Michael Duarte Goncalves

                  I think if I were going to refactor your code, I'd do something like this:

                  Code:
                  capture program drop EstFirstStage
                  program EstFirstStage
                      syntax, kreg(varname) iv(varlist) x(string) pretrend(string) set(integer)
                      quietly collect _r_b _r_se, tags(set[(`set')] model[(1)]): reg `kreg' `iv', r
                      quietly collect _r_b _r_se, tags(set[(`set')] model[(2)]): reg `kreg' `iv' `x'_`pretrend', r
                      quietly collect _r_b _r_se, tags(set[(`set')] model[(3)]): reg `kreg' `iv' `x'_`pretrend' i.prov_code, r
                  end
                  
                  capture program drop DrawFirstStage
                  program DrawFirstStage
                      syntax, kreg(varlist) iv(varlist) x(string) pretrend(string)
                      collect clear
                      local set = 1
                      foreach var of varlist `kreg' {
                          EstFirstStage, kreg(`var') iv(`iv') x("`x'") pretrend("`pretrend'") set(`set')
                          local++ set
                      }
                      collect style header result, level(hide)
                      collect style cell, nformat(%6.2f)
                      collect style cell result[_r_se], sformat("(%s)")
                      collect layout (set#colname[`iv']#result) (model)
                  end
                  
                  capture program drop EstSecondStage
                  program EstSecondStage
                      syntax, kreg(varname) iv(varlist) x(string) wave(integer) suffix(string)
                      quietly collect _r_b _r_se, tags(model[(1)]): ivregress 2sls `x'_00_03 (`kreg' = `iv'), r
                      local mn = ((`wave' - 1) * 3) + 2
                      quietly collect _r_b _r_se, tags(model[(`mn')]): ivregress 2sls `x'_`suffix' (`kreg' = `iv'), r // no controls
                      local++ mn
                      quietly collect _r_b _r_se, tags(model[(`mn')]): ivregress 2sls `x'_`suffix' (`kreg' = `iv') `x'_00_03, r // pre-trend
                      local++ mn
                      quietly collect _r_b _r_se, tags(model[(`mn')]): ivregress 2sls `x'_`suffix' (`kreg' = `iv') `x'_00_03 i.prov_code, r // pre-trend + province FE
                  end
                  
                  capture program drop DrawSecondStage
                  program DrawSecondStage
                      syntax, kreg(varlist) iv(varlist) x(string) pretrend(string) suffixes(string)
                      collect clear
                      local wave = 1
                      foreach var in `kreg' {
                          local suffix = word("`suffixes'", `wave')
                          EstSecondStage, kreg(`var') iv(`iv') x("`x'") wave(`wave') suffix("`suffix'")
                          local++ wave
                      }
                      collect style header result, level(hide)
                      collect style cell, nformat(%6.2f)
                      collect style cell result[_r_se], sformat("(%s)")
                      collect layout (colname[`kreg']#result) (model)
                  end
                  
                  capture program drop GenerateTables
                  program GenerateTables
                      syntax, kreg(varlist) iv(varlist) x(string) pretrend(string) suffixes(string)
                      DrawFirstStage, kreg(`kreg') iv(`iv') x("pop") pretrend("`pretrend'")
                      collect export first_order.tex, replace
                      DrawSecondStage, kreg(`kreg') iv(`iv') x("pop") pretrend("`pretrend'") suffixes("`suffixes'")
                      collect export second_order.tex, replace
                  end
                  I would personally rather maintain the above than what you have. This code is nice because it is compact, (I think) relatively easy to understand, it is general, and it is modular. I break the problem of building the two tables apart into smaller subproblems and I encapsulate those subproblems in their own commands. One could use this code quite easily by calling the -GenerateTables- command like this:

                  Code:
                  GenerateTables, kreg(cumpower_solar_norm_06_22 cumpower_solar_norm_06_14 cumpower_solar_norm_18_22) ///
                                  iv(com_sensitivity_solar_1) x("pop") pretrend("00_03") suffixes("04_22 04_14 16_22")
                  Which yields the following two tables:

                  Code:
                  . GenerateTables, kreg(cumpower_solar_norm_06_22 cumpower_solar_norm_06_14 cumpower_solar_norm_18_22) ///
                  >                 iv(com_sensitivity_solar_1) x("pop") pretrend("00_03") suffixes("04_22 04_14 16_22")
                  
                  Collection: default
                        Rows: set#colname[com_sensitivity_solar_1]#result
                     Columns: model
                     Table 1: 9 x 3
                  
                  -----------------------------------------------------
                                              |     (1)     (2)     (3)
                  ----------------------------+------------------------
                  (1)                         |                        
                    Sustainability solar $>1$ |   16.62  -10.24   54.42
                                              | (85.73) (89.79) (90.82)
                  (2)                         |                        
                    Sustainability solar $>1$ |   26.34   22.02   35.12
                                              | (12.62) (17.50) (25.35)
                  (3)                         |                        
                    Sustainability solar $>1$ |   -9.75  -32.26   19.31
                                              | (80.86) (83.32) (81.79)
                  -----------------------------------------------------
                  (collection default exported to file first_order.tex)
                  
                  Collection: default
                        Rows: colname[cumpower_solar_norm_06_22 cumpower_solar_norm_06_14 cumpower_solar_norm_18_22]#result
                     Columns: model
                     Table 1: 6 x 10
                  
                  --------------------------------------------------------------------------------------------------------------
                                       |       (1)       (2)      (3)     (4)      (5)     (6)     (7)      (8)     (9)     (10)
                  ---------------------+----------------------------------------------------------------------------------------
                  Change in solar, AAA |    135.20    376.81    21.84  -37.26                                                  
                                       |  (667.12) (1879.86) (210.64) (51.15)                                                  
                  Change in solar, BBB |     85.29                              208.27   16.62  -16.10                          
                                       |   (46.30)                            (114.62) (27.67) (19.66)                          
                  Change in solar, CCC |   -230.57                                                       -68.19   10.93   -56.08
                                       | (1841.82)                                                     (527.22) (32.60) (201.46)
                  --------------------------------------------------------------------------------------------------------------
                  (collection default exported to file second_order.tex)
                  
                  .
                  end of do-file
                  You could also just call DrawFirstStage and DrawSecondStage directly if you like. You could also write a "driver" for the script that resembles your original solution. I personally don't love this since I think it complicates things from a programmer perspective but doesn't actually make things much easier from a user perspective, but if you like the fact that the driver enforces one set of naming conventions or you feel it really does simplify things, here is how you might do that.

                  Code:
                  /***********************
                  // DRIVER STARTS HERE //
                  ***********************/
                  
                  local inst = 1                                                                    // = 1 use environmental sustainability index above one as instrument
                                                                                                  // = 2 use solar/wind potential
                                                                                                  // = 3 use interaction
                                                                                                  // = 4 use 1; 2 & 3 together
                                                                                                  
                  local energy = 1                                                                   // = 1 if solar
                                                                                                  // = 2 if wind
                  
                  *local vlist "logpop pop immig_flow emig_flow births"
                  local vlist "pop"
                  
                  local pretrend_period = "00_03"
                  
                  local wave_suffixes = "04_22 04_14 16_22"
                      
                  if `energy' == 1 {
                      local kreg = "cumpower_solar_norm_06_22 cumpower_solar_norm_06_14 cumpower_solar_norm_18_22"
                  }
                  else if `energy' == 2 {
                      display as error "Wind energy not yet implemented."
                      error 1
                  }
                  else {
                      display as error "Unrecognized energy type."
                      error 1
                  }
                  
                  if `inst' == 1 {
                      local iv "com_sensitivity_solar_1"                            
                      local labtitle "envsustain_above_one"
                  }
                  else if `inst' == 2 {
                      local iv "com_pv_potential"            
                      local labtitle "solar_potential"
                  }
                  else if `inst' == 3 {
                      local iv "inter_solar_above_1"            
                      local labtitle "interaction"
                  }
                  else if `inst' == 4 {
                      local iv "inter_solar_above_1 com_pv_potential com_sensitivity_solar_1"            
                      local labtitle "envsust_solar_pot_inter"
                  }
                  else {
                      display as error "Unrecognized inst type"
                      error 1
                  }
                  
                  // Here we iterate over each variable in vlist (see above). Two tables are created
                  // for each variable: one for the first order and one for the second order models.
                  foreach x of local vlist {
                      if "`x'" == "pop" {
                          local title "Change in population"
                      }
                      else if "`x'" == "logpop" {
                          local title "Log change in population"
                      }    
                      else if "`x'" == "immig_flow" {
                          local title "In-migrations (cumulative over)"
                      }    
                      else if "`x'" == "emig_flow" {
                          local title "Out-migrations (cumulative over)"
                      }    
                      else {
                          local title "Births (cumulative over)"
                      }
                      // The logic that builds the tables starts here.
                      GenerateTables, kreg(`kreg') iv(`iv') x("`x'") pretrend("`pretrend_period'") suffixes("`wave_suffixes'")
                  }
                  This code still needs work. It doesn't reproduce your latex table formatting precisely and I'm not sure I've implemented everything the original was supposed to do. Wind energy isn't implemented yet because your example data doesn't include those variables. I'm not sure what's happening with the interaction in inst == 3 and the original code is difficult to follow so I'm not keen to try to figure it out on my own, but I don't explicitly support interactions.

                  This is, I think, a decent proof of concept, and (in my humble opinion) worth the time to finalize, especially if you see yourself or someone else returning to this script in the future. However, since you didn't ask for a rewrite and it's not clear to me that you need (or particularly want) any of this, I'm happy to let this be a simple demonstration of how one might refactor your script. If you feel strongly that you'd like to move to code like mine I (and likely others) would be happy to talk you through some of the remaining problems.

                  Finally, here is the output for instance == 4 from my code. Not sure if this is what you are expecting to see or not, but let me know if you see problems with the output:

                  Code:
                  Collection: default
                        Rows: set#colname[inter_solar_above_1 com_pv_potential com_sensitivity_solar_1]#result
                     Columns: model
                     Table 1: 21 x 3
                  
                  -------------------------------------------------------------------
                                                      |       (1)       (2)       (3)
                  ------------------------------------+------------------------------
                  (1)                                 |                              
                    Inter. Sustain. ($>1$) x Solar P. |     -1.53     -1.57      1.62
                                                      |    (1.07)    (1.10)    (1.71)
                    Solar potential                   |      2.08      2.10     -1.20
                                                      |    (1.05)    (1.08)    (1.70)
                    Sustainability solar $>1$         |   2553.57   2591.44  -2591.13
                                                      | (1687.07) (1737.07) (2700.17)
                  (2)                                 |                              
                    Inter. Sustain. ($>1$) x Solar P. |      0.07      0.07      0.58
                                                      |    (0.05)    (0.07)    (0.41)
                    Solar potential                   |      0.03      0.03     -0.71
                                                      |    (0.02)    (0.03)    (0.46)
                    Sustainability solar $>1$         |    -86.72    -80.79   -911.83
                                                      |   (75.42)   (86.95)  (653.04)
                  (3)                                 |                              
                    Inter. Sustain. ($>1$) x Solar P. |     -1.60     -1.63      1.04
                                                      |    (1.04)    (1.07)    (1.61)
                    Solar potential                   |      2.05      2.07     -0.49
                                                      |    (1.03)    (1.05)    (1.53)
                    Sustainability solar $>1$         |   2640.27   2672.17  -1679.33
                                                      | (1644.12) (1690.84) (2553.15)
                  -------------------------------------------------------------------
                  (collection default exported to file first_order.tex)
                  
                  Collection: default
                        Rows: colname[cumpower_solar_norm_06_22 cumpower_solar_norm_06_14 cumpower_solar_norm_18_22]#result
                     Columns: model
                     Table 1: 6 x 10
                  
                  ----------------------------------------------------------------------------------------------------
                                       |     (1)     (2)     (3)     (4)     (5)     (6)     (7)    (8)    (9)    (10)
                  ---------------------+------------------------------------------------------------------------------
                  Change in solar, AAA |    3.59  -10.86  -21.88   -5.42                                              
                                       |  (5.94) (25.96) (11.92) (19.80)                                              
                  Change in solar, BBB |   36.70                           63.86  -22.90  -24.44                      
                                       | (34.98)                         (97.88) (46.88) (26.42)                      
                  Change in solar, CCC |    3.04                                                 -12.10 -13.44    7.10
                                       |  (6.93)                                                 (8.60) (6.25) (18.44)
                  ----------------------------------------------------------------------------------------------------
                  (collection default exported to file second_order.tex)
                  
                  .
                  end of do-file
                  Edit: fixed some typos and added the replace option to the two export commands in -GenerateTables-.
                  Last edited by Daniel Schaefer; 30 Dec 2024, 17:56.

                  Comment


                  • #10
                    By the way, I know you are expecting certain variables to appear or not appear in each table. In my version of the code you can fix that kind of thing quite easily by editing the two calls to -collect layout-.

                    Code:
                    collect layout (colname[`kreg']#result) (model)
                    The coefficients you want to include go in the square brackets.

                    Comment


                    • #11
                      Hi Daniel Schaefer

                      Incredible! Thank you for your amazing work. I will take a look in the next few days. I owe you a virtual coffee

                      Thank you very much, again.

                      Michael

                      Comment


                      • #12
                        Sure thing Michael!

                        One small correction while I have you; The last command looks like this:

                        Code:
                        capture program drop GenerateTables
                        program GenerateTables
                            syntax, kreg(varlist) iv(varlist) x(string) pretrend(string) suffixes(string)
                            DrawFirstStage, kreg(`kreg') iv(`iv') x("pop") pretrend("`pretrend'")
                            collect export first_order.tex, replace
                            DrawSecondStage, kreg(`kreg') iv(`iv') x("pop") pretrend("`pretrend'") suffixes("`suffixes'")
                            collect export second_order.tex, replace
                        end
                        I've still got the string "pop" hardcoded in here. I should be using the option instead.

                        Code:
                        capture program drop GenerateTables
                        program GenerateTables
                            syntax, kreg(varlist) iv(varlist) x(string) pretrend(string) suffixes(string)
                            DrawFirstStage, kreg(`kreg') iv(`iv') x("`x'") pretrend("`pretrend'")
                            collect export first_order.tex, replace
                            DrawSecondStage, kreg(`kreg') iv(`iv') x("`x'") pretrend("`pretrend'") suffixes("`suffixes'")
                            collect export second_order.tex, replace
                        end

                        Comment


                        • #13
                          Beautiful, it works perfectly well. Thank you so much.


                          I'd like to take this opportunity to write the following: Any advice you might have on how, from a general point of view, to create better code (when I say better code, I mean better in the computational, understandable sense), and any constructive comments on the subject, is most welcome.

                          (For the record: I'm an RA and I regularly work with poorly structured, unclear, uncommented code, etc.). So any source of information in this area to be a better programmer and not being like these people is welcome! Especially as it will save me time the next time I work on it)

                          Thanks a lot!

                          Michael
                          Last edited by Michael Duarte Goncalves; 13 Jan 2025, 09:50.

                          Comment


                          • #14
                            Gladly! Here are some general pieces of programming advice.

                            1. Good code is readable. That means commenting code when necessary, but more importantly the code itself should be easy to read. That means avoiding constructs that are confusing to your reader and using descriptive variable names. You want it to be as obvious as possible as to what the code does. If you find a clever way to do something in one line, but you know your reader is going to have to spend a lot of time figuring out your "brilliant" idea, and there is a simple way to do the same thing in three lines, the three line solution is probably better. Novices worry if the machine can understand their code while advanced programmers worry if a human reader can understand their code.

                            2. Good code is well-structured. Novice programmers spend a lot of time thinking about individual lines of code. Intermediate programmers know the syntax well enough to get stuff done and are focused on the way the code is structured overall. Advanced programmers know that, all else equal, simple is better and recognize when intermediate programmers over-engineer a program (as they are prone to do) and when novice programmers under-engineer a program (as they are prone to do).

                            3. Good code is modular. You generally want to take complex problems and break them into smaller subproblems which are, in some sense, separate from one another. Those "parts" should come together to form a larger whole that solves your higher order problem. This idea is foundational to object oriented programming, which is how most software is written, and it makes programs easier to write and maintain because it is easier to tell which "part" of the code governs the specific behavior you care about writing, fixing, or modifying. On a related note...

                            4. Good code is well encapsulated. This one can be tricky in Stata because of the way that data is globalized, but in general your "modular parts" should not affect one another except in ways that you explicitly define, because that can lead to emergent behavior that is difficult to debug. Some of these ideas are foundational to functional programming, and it might be worth googling things like "pure functions", "side effects", and "dependency injection" to learn more. Basically, you want to avoid "spaghetti code" where one variable in one part of the code has consequences for the way another seemingly unrelated part of the code operates. In the code above, I use the program command to encapsulate each part of the overall script. I also try to explicitly avoid referring to anything outside of the "scope" of each command: Instead I try to pass in everything the command needs as arguments. That way the command has an explicit "interface" that determines the way that it runs and the only thing that will affect the way the command runs are changes to the interface. This is also why (for example) you should usually avoid global macros and use local macros instead.

                            It's not really typical to write four commands like I do above in Stata when one will probably do. Part of the reason is that commands themselves are globalized (as far as I know, Stata does not support separate namespaces) and that can clutter up the global namespace. Notice that different design choices tend to involve tradeoffs. I write four commands to make the code more modular and flexible, but in doing so I add more command names to the namespace and possibly overwrite commands with the same names when I do so.

                            5. There is a tradeoff between generalizability and readability. On the one hand, we want our code to be general. General code is flexible and if you can do generalize your code, you can reuse your code in different situations. General code can be easy to modify. For example, my commands are general because if you need to change the value of `kreg' all you need to do is change a single option in your call to GenerateTables. You do not need to rewrite multiple lines across multiple commands. On the other hand, more general code is often harder to write, harder to read, and harder to understand. Generally speaking, you should write code that solves a very specific problem first. Then if you notice yourself writing very similar code in a lot of different places, that's where you want to generalize by noticing the pattern and writing something more abstract that deals with problems that follow that pattern. If you notice yourself copying and pasting some code, then making small changes to apply it in a slightly different context, that's often a sign you should generalize with a for loop, command, or some other more general construct.
                            Last edited by Daniel Schaefer; 13 Jan 2025, 11:10.

                            Comment


                            • #15
                              Daniel Schaefer: Thank you very much again for your pieces of advices (and mostly for your time!).

                              This is really appreciated. And I like your approach:

                              1. Code has to be simple. So often, I and other people with an intermediate knowledge of Stata think that maybe, to be good at Stata, you have to make extremely complicated (and uncommented) code, using for loops all the time. But in fact, these for loops are sometimes useless and can be written more simply.

                              2. Work on a problem locally, and then, according to the pattern, generalize the whole thing to avoid a lot of repetition (and above all, to avoid human errors too, of forgetting to change a variable name, parameter or whatever).
                              I'd like to say that I'm starting to have this little reflex of working on local stuff and, all of a sudden, I say to myself: “But actually, I can do simpler here and less laborious!”, especially when I see myself doing copy/paste. Here's hoping I'm on the right track... Mostly thanks to Statalist comments and suggestions of improvement.

                              To this day, I'm unable to create programs like you did above, but I hope that experience and the crashes and failures will make me as good a programmer as you are. Thank you again for everything.

                              Comment

                              Working...
                              X