Announcement

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

  • Stata programming: r-class program refuses to return the desired macro

    Dear statalisters,

    I am currently trying to write a little program with the aim of automating a procedure to interpret factor analysis solution as suggested by Grice and Harris (1998) and Grice(2001), since this is not yet available in Stata. My idea was to write something like a simple postestimation command that would plot the factor score coefficient estimates in descending order and actually this works out fine.
    I also want the program to be able to calculate the multiple correlations of the factors. To do that for both rotated and unrotated factor solutions one needs to distinguish these two cases by accessing the stored macro r(rtext). For example, r(rtext) would contain the string " (unrotated)" in case of an unrotated factor solution.
    So far, everything works fine.

    However, when running my program the local macro r(rtext) stored by factor gets overwritten. So, if no rotation has been carried out and the program is run two times in a row, it wont be able to calculate the multiple correlations in the second go.
    So I thought: Why not simply store the content of factor's r(rtext) in a local macro and let the program return it again using the exact same name r(rtext). Then the program can still access this information in the second go.

    And here comes the problem: I cannot manage to let Stata store the actual content of r(rtext) - for example the string " (unrotated)" - as content of r(rtext). Instead it stores the string "r(rtext)" instead.

    I am pretty sure I am having a basix misunderstanding of how stata evaluated local macros or something, but I can't seem to get it fixed, so any advice will be highly appreciated.
    I hope the problem gets clear when you have a look at the code. I think it is really just about the line in the beginning where the r(rtext) from factor is stored as the local macro rotation and the line in the end where the program is meant to return the content of `rotation' in as the local macro r(rtext) again.

    Here comes the code:
    Code:
    sysuse auto, clear
    
    capture program drop fsinter
    *! fsinter v1.0.0, Boris Ivanov, 21Apr2017
    
    program define fsinter, rclass
    version 14.2
    
    
    local rotation r(rtext)
    
    if `rotation' == " (unrotated)" {        // Multiple correlations for unrotated factor solution
        mat phi = e(Phi)
        mat lambda = e(L)
        mat S = e(C)
        
        local f=e(f)
        mat A = phi*lambda'*inv(S)*lambda*phi
        
        mat rho = J(`f',1,.)
        forvalues i=1/`f' {
            mat rho[`i',1]=A[`i',`i']
            local rho2_f`i': display %6.3f A[`i',`i']
        }
        
        mat rho_sq = J(`f',1,.)
        forvalues i=1/`f' {
            mat rho_sq[`i',1]=sqrt(A[`i',`i'])
            local rho_f`i': display %6.3f sqrt(A[`i',`i'])
        }
    }
    
    else {        // Multiple correlations for rotated factor solution
        mat phi = e(r_Phi)
        mat lambda = e(r_L)
        mat S = e(C)
        local f=e(f)
        mat A = phi*lambda'*inv(S)*lambda*phi
        
        mat rho = J(`f',1,.)
        forvalues i=1/`f' {
            mat rho[`i',1]=A[`i',`i']
            local rho2_f`i': display %6.3f A[`i',`i']
        }
        
        mat rho_sq = J(`f',1,.)
        forvalues i=1/`f' {
            mat rho_sq[`i',1]=sqrt(A[`i',`i'])
            local rho_f`i': display %6.3f sqrt(A[`i',`i'])
        }
    }
    
    
    preserve
    set autotabgraphs on    // Makes Stata stack the graph in tabs in the graph display window
    
    qui predict fs_*
    
    mat scoef = r(scoef)    
    qui xsvmat, from(scoef) names(col) rownames(item) fast // Store matrix of factor score coefficients as dataset
    
    qui replace item = substr(item,1,15) // truncating item names (for marker labels)
    
    qui gen rank=.            // gen var for ranking items by factor score coeff on item
    
    forvalues i=1/`f' {
        gsort - Factor`i'    // sort factor score coeffs descendingly
        qui replace rank=_n        // adjust the ranking variable accordingly
        twoway (scatter  Factor`i' rank, ///
                 msize(medium) mlab(item) mlabangle(20) mlabpos(1) mlabsize(vsmall) connect(l) ///
                 ytitle("Factor `i' score coefficients") ///
                 note("Factor score determinacy: " ///
                      "{&rho} = `rho_f`i''" ///
                      "{&rho}{superscript:2} = `rho2_f`i''", size(vsmall)) ///
                 legend(off) ///
                 name(factor`i', replace))
    }
    
    return scalar f = `f'
    return matrix rho_sq = rho_sq  
    return matrix rho = rho
    return local rtext `rotation'
    
    set autotabgraphs off
    restore
    end
    
    ** Lets run the program and see what it will return:
    qui factor price mpg rep78 gear_ratio displacement  // unrotated factor solution
    fsinter
    return list
    
    qui factor price mpg rep78 gear_ratio displacement  // rotated factor solution
    qui rotate
    fsinter
    return list
    You may find a screenshot of the return list output attached. As you can see r(rtext) does not contain the original content of factor's r(rtext) (e.g. " (unrotated)") but the string "rtext"...
    Attached Files
    Last edited by Boris Ivanov; 21 Apr 2017, 09:07.

  • #2
    You need something more like

    Code:
     
     local rotation "`r(rtext)'"
    or
    Code:
    local rotation = r(rtext)
    as otherwise Stata will indeed just copy the text you supplied without trying to evaluate it. That's the advertised behaviour of local, that
    Code:
    local foo contents
    puts literal text
    contents into local macro foo. The text in question being the name of something else or a place where something else is stored doesn't change that. Indeed, if mentioning a name always meant evaluation on the fly, it would be hard to pass names around....

    Comment


    • #3
      Thank you Nick, I see that r(rtext) needs to be evaluated when put into the local. I guess I wasn't able to see the wood for the trees.

      Comment


      • #4
        Here the need is to see the detail that bites, not the big picture.

        Comment


        • #5
          Actually you are right

          Comment

          Working...
          X