Announcement

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

  • cvpermute() to run Stata command for all permutations of categorical covariate ?

    Dear list members,

    I need help on a probably rather basic issue, being naive in Mata and currently not having alas much time to put myself to practice and read the manual.

    I need to run an estimation command for all the permutations of the levels of a categorical variable. Let's assume the categorical variable has levels 1 to 5. I understood the best way to obtain permutations is to use Mata, and more precisely cvpermute(). If there is an equally or more effective and not too code-consuming way with Stata, please enlighten me. I understood I can loop over the permutations of a column vector containing the levels of the categorical variable in the following way:

    Code:
    mata:
    levels = (1\2\3\4\5)
    info = cvpermutesetup(levels, unique=1)
    while ((levels=cvpermute(info)) != J(0,1,.)) {
        for (i=1; i<=6; i++) {
            // more code here
        }    
    }
    end
    Now, if I were to code in Stata, my approach within each loop would be to extract as scalars the vector elements to then be able to write something like

    Code:
    recode country (1=`=el`1'') (2=`=el`2'') (3=`=el`3'') (4=`=el`4'') (5=`=el`5'')
    so that for every permutation, the first to fifth position are occupied by (sometimes) changing row values, and the resulting recoded variable will differ. However, I understand the latter code will not work within a Mata loop, although I guess there might be ways to make it work that I am unaware of. Immediately after recode, I will then need to call an estimation command, again within the loop. If there is no way to use recode or this other estimation command within the Mata loop, then I am at a loss about how to proceed, and I would need even more general guidance.

    Apologies for the lack of data, I guess/hope the question is fairly complete without it.
    I'm using Stata/MP 17

  • #2
    I'm assuming that you *don't* want a permutation test, as you would get with the built-in Stata -permute- command. Rather, I'm assuming that you want to execute your estimation command once for each of the possible permutations of the integers sequence 1, 2, 3, 4, 5.

    If that is right, here's an approach, which is similar to what you wrote, but which doesn't have a for-loop inside the while-loop. I don't understand what you wanted the for-loop to do. My approach is to first use Mata to create a numbered list of locals in Stata that contain the permuted values, and then loop over those locals. I suppose something similar could be done by calling Stata within the Mata program, but I like separating uses of Mata and Stata:

    Code:
    // Use Mata to create locals containing permutations of the integers. The Mata code
    // could be combined into fewer lines, but I favor readability over length.
    mata:
    levels = (1\2\3\4)  // Shorter example for illustration
    info = cvpermutesetup(levels, unique=1)
    i = 0
    while ((levels=cvpermute(info)) != J(0,1,.)) {
        ++i
        locname = "perm" + strofreal(i)
        permstring = invtokens(strofreal(levels'))
        st_local(locname, permstring)
    }
    end
    //
    // Loop over the permutations contained in locals.
    local nperm = 4 * 3 * 2 * 1
    forval i = 1/`nperm' {
       di " Do something with perm`i' = `perm`i''"
      }
    
     Do something with perm1 = 1 2 3 4
     Do something with perm2 = 1 2 4 3
     Do something with perm3 = 1 3 2 4
     Do something with perm4 = 1 3 4 2
     Do something with perm5 = 1 4 2 3
     Do something with perm6 = 1 4 3 2
     Do something with perm7 = 2 1 3 4
     Do something with perm8 = 2 1 4 3
     Do something with perm9 = 2 3 1 4
     Do something with perm10 = 2 3 4 1
     Do something with perm11 = 2 4 1 3
     Do something with perm12 = 2 4 3 1
     Do something with perm13 = 3 1 2 4
     Do something with perm14 = 3 1 4 2
     Do something with perm15 = 3 2 1 4
     Do something with perm16 = 3 2 4 1
     Do something with perm17 = 3 4 1 2
     Do something with perm18 = 3 4 2 1
     Do something with perm19 = 4 1 2 3
     Do something with perm20 = 4 1 3 2
     Do something with perm21 = 4 2 1 3
     Do something with perm22 = 4 2 3 1
     Do something with perm23 = 4 3 1 2
     Do something with perm24 = 4 3 2 1
    You could, of course, access elements of each local with constructions like
    Code:
    word("`perm10'", 3)
    If this isn't what you want, feel free to post back.

    Comment


    • #3
      Dear Mike Lacy, you assumed correctly, and nailed it. The for loop was probably an attempt to replace what I now can clearly do separately, with forval in Stata, after the Mata chunk - precisely using word().

      Code:
      mata:
      levels = (1\2\3\4\5\6)
      info = cvpermutesetup(levels, unique=1)
      i = 0
      while ((levels=cvpermute(info)) != J(0,1,.)) {
          ++i
          locname = "perm" + strofreal(i)
          permstring = invtokens(strofreal(levels'))
          st_local(locname, permstring)
      }
      end
      
      local nperm = 6 * 5 * 4 * 3 * 2 * 1
      forval i = 1/`nperm' {
          forval j=1/6 {
              loc el`j' = word("`perm`i''", `j')
              if word("`perm`i''", `j')=="1" local eltr `el`j''
          }
          recode country (1=`el1') (3=`el2') (12=`el3') (20=`el4') (21=`el5') (22=`el6')
           
          /*run estimation command here, and post results elsewhere*/
          
          recode country (`el1'=1) (`el2'=3) (`el3'=12) (`el4'=20) (`el5'=21) (`el6'=22)
      }
      Thanks!
      I'm using Stata/MP 17

      Comment

      Working...
      X