Announcement

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

  • Index for minimum of a column/variable

    I'm trying to find the row numbers corresponding to the minimum value in each column of a matrix. A search turned up a Mata function called minindex, but the documentation has the word "void" in front of the function reference, which may explain why I haven't gotten it to work. I'm currently working with the columns of a matrix, but I could turn the matrix into a dataset if it made things easier. Thanks.

  • #2
    Some working examples are here:

    http://www.statalist.org/forums/foru...ctor-or-matrix
    You should:

    1. Read the FAQ carefully.

    2. "Say exactly what you typed and exactly what Stata typed (or did) in response. N.B. exactly!"

    3. Describe your dataset. Use list to list data when you are doing so. Use input to type in your own dataset fragment that others can experiment with.

    4. Use the advanced editing options to appropriately format quotes, data, code and Stata output. The advanced options can be toggled on/off using the A button in the top right corner of the text editor.

    Comment


    • #3
      As documented, minindex() returns the results in one of its argument instead of as a return.

      HTML Code:
      minindex(v, k, i, w) returns in i and w the indices of the k minimums of v.
      The following is an example of using minindex() to find the index of min value of each column of a Stata matrix and save the result in another Stata matrix user specified. If there are ties, the first index is returned.

      Code:
      mata:
      void get_minindex(string scalar m, string scalar idx)
      {
          real matrix A
          real scalar i
          real rowvector res
          real colvector v
          
          A = st_matrix(m)
          
          /*the min index of column i is stored in res[1, i]*/
          res = J(1, cols(A), .)
          
          /*get the min index*/
          for(i=1; i<=cols(A); i++){
              minindex(A[.,i], 1, v=., .)
              res[1, i] = v[1, 1]
          }
          
          /*save result into a Stata matrix idx*/
          st_matrix(idx, res)
      }
      end
      The following is a quick test:


      Code:
      . mat define A = (2, 6, 7\3, 5, 7\2, 4, 8)
      
      . mat list A
      
      A[3,3]
          c1  c2  c3
      r1   2   6   7
      r2   3   5   7
      r3   2   4   8
      
      . mata:get_minindex("A", "minA")
      
      . mat list minA
      
      minA[1,3]
          c1  c2  c3
      r1   1   3   1

      Comment


      • #4
        Hua Peng (StataCorp) I would like to point out that the proper use of minindex() in the code is not at all apparent from the documentation. Having "i=." is not mentioned in the documentation once. It just has "i" in that argument position, which returns an error when you try to do exactly what the manual says. I am referrring to "Stata 16 help for mf_minindex".

        Comment


        • #5
          Charlie, Hua has used a bit of a shortcut which is legal syntax in Mata, because Mata support defining variables at the same time as using them. Consider a simple example to calculate the area of a circle:

          Code:
          mata:
            // define radius while defining the area calculation
            area = 2 * pi() * (radius=3)^2
            area
           
            // pre-define a radius
            radius = 1
            area = 2 * pi() * (radius)^2
            area
          end
          with output

          Code:
          :   radius, area
                           1             2
              +-----------------------------+
            1 |            3   56.54866776  |
              +-----------------------------+
          ...
          :   radius, area
                           1             2
              +-----------------------------+
            1 |            1   6.283185307  |
              +-----------------------------+
          A toy example using minindex() follows from Example 1 in the help page.

          Code:
          mata:
            v = (3,1,5,7,6)
            v
           
            // This fails because i and w don't exist yet.
            minindex(v, 2, i, w)
           
            // Declare i and w during the function call. Mata first creates i and w as null valued real scalars, then passes them to minindex.
            // Minindex will redefine those later.
            minindex(v, 2, i=., w=.)
            i
            w
           
            // Pre-define ii and ww, then call minindex.
            ii = .
            ww = .
            minindex(v, 2, ii=., ww=.)
            ii
            ww
           
            asserteq(i, ii)
            asserteq(w, ww)
          end

          Originally posted by Charlie Hammond View Post
          Hua Peng (StataCorp) I would like to point out that the proper use of minindex() in the code is not at all apparent from the documentation. Having "i=." is not mentioned in the documentation once. It just has "i" in that argument position, which returns an error when you try to do exactly what the manual says. I am referrring to "Stata 16 help for mf_minindex".

          Comment


          • #6
            For what it's worth I use this Mata function to generate the row indexes corresponding to the column minima. It returns a pointer row vector of the indexes that allows for the possibility that there are multiple rows that correspond to the same column minimum.
            Code:
            cap mata mata drop minind()
            set matastrict off
            
            mata
            
            function minind(y) {
            real cmy
            pointer pmy
            pmy=J(1,cols(y),NULL)
            cmy=colmin(y)
            for (j=1;j<=cols(y);j++) {
             pmy[j]=&(select((1::rows(y)),(y[.,j]:==cmy[j])):+0)
            }
            
            return(pmy)
            
            }
            
            end
            So
            Code:
            : y=(1\2\3\4),(2\2\3\2),(.\2\3\4)
            
            : my=minind(y)
            
            : *my[1]
              1
            
            : *my[2]
                   1
                +-----+
              1 |  1  |
              2 |  2  |
              3 |  4  |
                +-----+
            
            : *my[3]
              2
            (Note: Adding zero in the function's pmy[j]= line accommodates a quirk of how pointers work; see this thread: https://www.statalist.org/forums/for...ich-they-point)
            Last edited by John Mullahy; 09 Apr 2021, 08:42. Reason: typo

            Comment

            Working...
            X