Announcement

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

  • "Nesting" a local macro in a matrix reference in Mata

    I have a long list of observations from many countries. Each person was asked to rate six items on a 0-10 scale. I would like to compare the rankings of these items across countries, where the ranking is determined by the average ratings. I will also compare each country to an overall "world" ranking, determined the same way.

    The world rankings were easy to do, and I used Mata in just one line, to sort a matrix I created:
    Code:
    // collect the overall averages
    foreach i of numlist 1/6 {
        qui sum itemA`i'
        local a`i' = r(mean)
    }
    // put into a matrix with item# in first col and rating in second
    matrix ratingsworld = J(6,2,.)
    foreach i of numlist 1/6 {
        matrix ratingsworld[`i',1] = `i'
        matrix ratingsworld[`i',2] = `a`i''
    }
    matrix list ratingsworld
    // sort according to item rating. note that the highest ranked is now in sixth row.
    mata : st_matrix("ratingsworld", sort(st_matrix("ratingsworld"), 2)) 
    matrix list ratingsworld
    // gen new vars showing the world rank of each item
    foreach i of numlist 1/6 {
        local v = ratingsworld[6-`i'+1,1]
        gen rankA`v'w = `i'
    }
    Now I would like to do the same thing for each country, creating variables rankA1c-rankA6c that contain the rankings at the country level. The first part of the code is the same. Where I'm having trouble is the Mata line. st_matrix() brings the matrix into Mata, and I know st_local() can bring a local macro into Mata. The problem lies in combining them. I need to refer to a matrix using a local macro, since there will be a different matrix for each country. This is one version I have tried:
    Code:
    levelsof cntry, local(levels)
    foreach lvl of local levels {
        // avg by cntry
        foreach i of numlist 1/6 {
        qui sum itemA`i' if cntry==`lvl'
        local a`i' = r(mean)
        }
        // into item-rating matrix
        matrix ratings`lvl' = J(6,2,.)
        foreach i of numlist 1/6 {
            matrix ratings`lvl'[`i',1] = `i'
            matrix ratings`lvl'[`i',2] = `a`i''
        }
        matrix list ratings`lvl'
        // sort
        mata : st_matrix("ratingsworld"+st_local("lvl"), sort(st_matrix("ratingsworld"+st_local("lvl"),2))
        matrix list ratings `lvl'
    }
    This gives the error "unexpected end of line, <istmt> incomplete." I also tried replacing the mata line with the previously working line in the code at the top (without the "lvl" macro). In this case, the code runs, but the mata line appears to be ignored. Running it with trace on, it looks like Stata is ignoring it entirely. Here is a short snippet of the results:
    Code:
        ---------------------------------------------------------------------------------------------------- end _matrix_cmds.List ---
      - exit
      ----------------------------------------------------------------------------------------------------------- end _matrix_cmds ---
    - mata : st_matrix("ratingsworld", sort(st_matrix("ratingsworld"), 2))
    - matrix list ratings`lvl'
    = matrix list ratings24
      --------------------------------------------------------------------------------------------------------- begin _matrix_cmds ---
    My question is, how can I run this line of code within the loop, referring to a matrix using a local macro? And why is Stata apparently ignoring the Mata line within the loop?

  • #2
    The reason for the error has nothing to do with local macro, the following line is missing a close parenthesis.

    Code:
     
     mata : st_matrix("ratingsworld"+st_local("lvl"), sort(st_matrix("ratingsworld"+st_local("lvl"),2))
    Add a close parenthesis to the end should fix your problem.

    Comment


    • #3
      Thanks for noticing that, Hua. However, the code still yields the "unexpected end of line, <istmt> incomplete" error.

      I found some evidence (old statalist posts) that it is not possible to include Mata lines in a regular Stata loop (perhaps because the Stata loop misunderstands the "end" of the Mata line). Instead I solved my problem by separating the Stata and Mata commands into separate loops, which run one after the other. For anyone interested, here is my final (working!) code:

      Code:
      levelsof cntry, local(levels)
      // make the unsorted matrices
      foreach lvl of local levels {
          // avg by cntry
          foreach i of numlist 1/6 {
          qui sum itemA`i' if cntry==`lvl'
          local a`i' = r(mean)
          }
          // into item-rating matrix
          matrix ratings`lvl' = J(6,2,.)
          foreach i of numlist 1/6 {
              matrix ratings`lvl'[`i',1] = `i'
              matrix ratings`lvl'[`i',2] = `a`i''
          }
      }
      // sort each matrix in mata
      mata
          levels = tokens(st_local("levels"))
          for(i=1;i<=length(levels); i++) {
              st_matrix("ratings"+levels[i], sort(st_matrix("ratings"+levels[i]), 2))
          }
      end
      // save the rankings to new variables
      foreach i of numlist 1/6 {
          gen rankA`i'c = .
      }
      foreach lvl of local levels {
          foreach i of numlist 1/6 {
              local v = ratings`lvl'[6-`i'+1,1]
              replace rankA`v'c = `i' if cntry==`lvl'
          }
      }

      Comment


      • #4
        Hua is right. This is the typical error, when one or more parathesis is missing.
        I suggest that You change your preferences in the editor such that matching paranthesis are easier to see:

        Click image for larger version

Name:	Stata editor braces.png
Views:	1
Size:	58.8 KB
ID:	1339970


        After that my only advice is to look at how the paranthesis match in your code

        Brw it is often an good idea to limit the number of matching paranthesis inside other pairs of paranthesis
        Kind regards

        nhb

        Comment

        Working...
        X