Announcement

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

  • swap columns and rows of e(b) and e(V)

    Hi all,

    I am new to mata, but I think this issue can be solved by mata.

    I am wondering how to swap rows (and columns) based on the names of the columns (and rows) in stata. For example, the e(b) matrix I get is shown in Impage 3.png. What I would like to achieve is to swap columns so that all the columns associated with equation 1 (equ1) precede all columns associated with equation 2 (equ2) etc. And for columns of a single equation, the variables are also in a particular order-cons, lnmp lnp1 lnp2 lnp3 lnp4 lnp5 lnp6.

    I have already saved the result in result.ster (https://1drv.ms/u/s!An6r3b9xWElTl0ETiaVzoRzSJST2).

    Thank you all in advance
    Attached Files

  • #2
    I don't see Mata as relevant to the solution. I think this is a tedious problem, and I'm not up to providing a complete solution, but I can suggest how I would approach it, at least the part that involves moving columns of e(b). Also, your description of what you want is not clear to me, so I'm *guessing* you to mean that you want a matrix with all the equ1 columns first, then all the equ2 columns, and then all the equN columns. Within each block of (e.g.) equ1, I'm *guessing* you want columns ordered as they were in e(b).

    First, I'd use the extended macro function -colnames- to obtain a local containing the column names (see - help extended_fcn-).
    Code:
    mat B = e(b)
    local cnames: colnames B
    Then, I would loop over the column names, and concatenate the columns associated with a particular equation (e.g., equ1) into a Stata matrix. For example:
    Code:
    local foundfirst = 0
    local j = 0
    foreach cn of local cnames {
         local ++j
         if (strpos("`cn'", "equ1") & (`foundfirst' == 0)) { 
              mat EQ1 = B[1..`R',`j']
              local foundfirst == 1
         }
         else if (strpos("`cn'", "equ1") & (`foundfirst' == 1)) {
              mat EQ1 = (EQ1, B[1..`R',`j']
         }
    }
    Presuming you do this with all of equ1, ..., equN, you could then put them together as you like:
    Code:
    mat EQ = (EQ1, EQ2, ..., EQN)
    Since I didn't have anything on which to test this code, there are likely errors, but it should at least give the idea of my approach.
    Last edited by Mike Lacy; 20 Nov 2018, 12:25.

    Comment


    • #3
      Originally posted by Mike Lacy View Post
      I don't see Mata as relevant to the solution. I think this is a tedious problem, and I'm not up to providing a complete solution, but I can suggest how I would approach it, at least the part that involves moving columns of e(b). Also, your description of what you want is not clear to me, so I'm *guessing* you to mean that you want a matrix with all the equ1 columns first, then all the equ2 columns, and then all the equN columns. Within each block of (e.g.) equ1, I'm *guessing* you want columns ordered as they were in e(b).

      First, I'd use the extended macro function -colnames- to obtain a local containing the column names (see - help extended_fcn-).
      Code:
      mat B = e(b)
      local cnames: colnames B
      Then, I would loop over the column names, and concatenate the columns associated with a particular equation (e.g., equ1) into a Stata matrix. For example:
      Code:
      local foundfirst = 0
      local j = 0
      foreach cn of local cnames {
      local ++j
      if (strpos("`cn'", "equ1") & (`foundfirst' == 0)) {
      mat EQ1 = B[1..`R',`j']
      local foundfirst == 1
      }
      else if (strpos("`cn'", "equ1") & (`foundfirst' == 1)) {
      mat EQ1 = (EQ1, B[1..`R',`j']
      }
      }
      Presuming you do this with all of equ1, ..., equN, you could then put them together as you like:
      Code:
      mat EQ = (EQ1, EQ2, ..., EQN)
      Since I didn't have anything on which to test this code, there are likely errors, but it should at least give the idea of my approach.
      Thanks, Mike. This strategy works well.

      Comment


      • #4
        Bo: While Mike's solution works for your purposes, if you wanted to do this work in Mata I think it's possible with careful use of st_matrixcolstripe(.) and sort(.). Here is the essence of the idea.
        Code:
        mata
        
        b=st_matrix("e(b)")
        v=st_matrix("e(V)")
        sb=st_matrixcolstripe("e(b)")
        sba=sb,strofreal(1::rows(sb))
        sbas=sort(sba,(1,2))
        sind=strtoreal(sbas[.,cols(sbas)])
        bsort=b[sind]
        vsort=v[sind,sind]
        
        end
        In your example I think
        Code:
        sb=st_matrixcolstripe("e(b)")
        will return a kx2 string matrix with nonmissing elements in the first column (check this). If so then the key issue is whether
        Code:
        sbas=sort(sba,(1,2))
        orders the names as you desire. You might have to play around with the sort order to get the results you want, but I think it's doable.

        Comment

        Working...
        X