Search code examples
loopslatexstatatex

How to use loops with texdoc


Say that I run these two regressions and save the output to be used with texdoc to create a LaTeX file:

capture ssc install texdoc
sysuse auto2, clear
global spec1 "if foreign"
global spec2 "if !foreign"

foreach spec in 1 2 {
    reg price mpg ${spec`spec'}
        global b_mpg_`spec': di %6.2fc _b[mpg]
        global se_mpg_`spec': di %6.2fc _se[mpg]
        
        qui test mpg=0
        global mpg_p_`spec': di %12.2fc r(p)
        glo mpg_star_`spec'=cond(${mpg_p_`spec'}<.01,"***",cond(${mpg_p_`spec'}<.05,"**",cond(${mpg_p_`spec'}<.1,"*","")))
        
        local N=e(N)
        global N_`spec': di %12.0fc `N'
        scalar r2=e(r2)
        global r2_`spec': di %6.3fc r2
        
        sum price if e(sample)
        global ymean_`spec': di %12.2fc r(mean)
}

I can then use texdoc to create the .tex file as follows:

texdoc init "test.tex", replace force
tex MPG          & ${b_mpg_1}${mpg_star_1} & ${b_mpg_2}${mpg_star_2} \\
tex              & (${se_mpg_1})           & (${se_mpg_2}) \\ \addlinespace
tex Y Mean       & ${ymean_1}              & ${ymean_2} \\
tex Observations & $N_1                    & $N_2 \\
tex R-Squared    & $r2_1                   & $r2_2 \\
tex Sample       & Foreign                 & Domestic
texdoc close

How can I instead use loops (e.g., foreach or forvalues) in this last chunk of code so as to not have to write out each variable column more than once? In this example, there are only two columns, but in other examples, I have up to 9 columns, and so it quickly gets unwieldy to have to put in each column.

It would be trivial to add rows using a loop. However, I am not sure how to add different columns - I don't know how to add a loop within a line that begins with tex. And if I do something like:

tex MPG
foreach i in 1 2 {
tex          & ${b_mpg_`i'}${mpg_star_`i'}
}
tex \\

the tex code goes onto multiple lines and so is unusable (and is also very inelegant).


Solution

  • Use a loop to build up a string of the desired output and then use texdoc to write the string to the file:

    // Initialize variables to store the output strings for each column
    local tex_MPG ""
    local tex_se_MPG ""
    local tex_Y_Mean ""
    local tex_Observations ""
    local tex_R_Squared ""
    local tex_Sample ""
    
    // Loop over the two specifications
    foreach spec in 1 2 {
        // Build up the output strings for each column
        local tex_MPG = "${tex_MPG} & ${b_mpg_`spec'}${mpg_star_`spec'}"
        local tex_se_MPG = "${tex_se_MPG} & (${se_mpg_`spec'})"
        local tex_Y_Mean = "${tex_Y_Mean} & ${ymean_`spec'}"
        local tex_Observations = "${tex_Observations} & ${N_`spec'}"
        local tex_R_Squared = "${tex_R_Squared} & ${r2_`spec'}"
        local tex_Sample = "${tex_Sample} & ${cond(`spec'==1,"Foreign","Domestic")}"
    }
    
    // Initialize the LaTeX file
    texdoc init "test.tex", replace force
    
    // Write the output strings to the file
    tex `tex_MPG' \\
    tex `tex_se_MPG' \\ \addlinespace
    tex `tex_Y_Mean' \\
    tex `tex_Observations' \\
    tex `tex_R_Squared' \\
    tex `tex_Sample'
    
    // Close the LaTeX file
    texdoc close

    Loops are used to build up the output strings for each column, and then writes the strings to the LaTeX file using the tex command. The \addlinespace command adds a small vertical space between rows in the table.

    Thanks.