Announcement

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

  • Getting the rowname for the max value in a matrix (using either Mata or Stata)

    Hi All,

    I am looking to get the rowname of the max value in a matrix and store it as a local. I have got to the following steps easy enough:

    Code:
    sysuse auto
    tab foreign, matcell(XX)
    mata : max(st_matrix("XX"))
    I cannot figure how to use "st_matrixrowstripe" to return the rowname. I am also assuming (correctly or not) that there is a way of combining the max(st_matrix()) and st_matrixrowstripe() components in a single line? Then, I'll only need to use st_local() extract the row name corresponding to the max value in the matrix for further use within Stata...

    Thank you in advance!

    Ariel

  • #2
    What will you do if there is more than one route with the max value? Will you pick the first one? Is it forbidden?

    Comment


    • #3
      Great question! I guess that I’ll take one of them at random. Right now I just want to solve this more simple problem of extracting the name corresponding to that max value.

      Comment


      • #4
        This shows some technique in Mata:

        Code:
        sysuse auto
        tab rep78, matcell(XX)
        
        mata:
          XX = st_matrix("XX")
          XX
         
          // identify the index position in which the row is equal to the max value.
          // Multiple values will be returned should there be more than one row equal to the max value.
          idx = selectindex(XX:==max(XX))
          // Alternative: idx = select((1..rows(XX))', XX:==max(XX))
          idx
         
          // Not shown: pick one if more than one row is returned (e.g., pick the first or last one, pick at random).
          // Now get the corresponding rowstripe
          st_matrixrowstripe("XX")[idx,.]
        end

        Comment


        • #5
          Thank you, Leonardo!

          I need to get this result back into Stata. Can I turn the matrixrowstripe (rowname) into a local for export?

          Thank you,

          Ariel

          Comment


          • #6
            You can do that with st_local() and decide how you want to handle the “equation” side of the rowstripe (in your toy example it’s blank so you can ignore it).

            Comment


            • #7
              Alternatively, you could pass the index back in a local and subset the Stata matrix and I think that will keep the row and colstripes intact.

              Comment


              • #8
                Okay, thanks! I’ll try that tomorrow!

                Comment


                • #9
                  Thank you, Leonardo. The line producing the index
                  Code:
                   idx = selectindex(XX:==max(XX))
                  is really the key!I. Adding
                  Code:
                  st_local("idx", strofreal(idx))
                  gets me that row index number back into Stata. I can now turn my attention to choosing the row when there are ties...

                  Comment


                  • #10
                    Hi Leonardo,

                    Can you please show me how to get the index for the max random value of the following code (see text below highlighted in red)?

                    Thank you!

                    Ariel

                    Code:
                    // generate a matrix where there are multiple rows with the same maximum value
                      mat XX = (2,8,30,30,18,11)
                    
                    mata:
                      XX = st_matrix("XX")
                    
                       // get the index for the maximum value (in this case there will be two)
                      idx = selectindex(XX:==max(XX))'
                    
                      // get the count of maximum values 
                      rowscnt = rows(idx)
                     
                      // if there are multiple maximum values, generate random values for each
                      if (rowscnt > 1 ) {
                          rand_vals = runiform(1, rowscnt)'
                          // I am not sure if the two matrices need to be joined in order to get the new maximum value?   
                          max_matrix = idx , rand_vals
                      
                    
                         // this is the line that I need help with. I need to find the index value (from the "idx" matrix) that represents the maximum random value from among the two maximum index values
                         // my guess is that there is a way for me to get the index from "idx" that corresponds to the row value of "rand_vals", without having to enjoin the two matrices? In any case, this
                         // following line of code does not work
                         idx= selectindex(max_matrix:==max(max_matrix))'
                      }
                    
                      // make available to Stata
                      st_local("idx", strofreal(idx))
                    
                    end

                    Comment


                    • #11
                      Here's one way to get the index of the maximum value of a vector (randomly chosen for multiple maxima):

                      Code:
                      real scalar index_of_max(real vector x)
                      {
                          real vector index
                          
                          
                          if (length(x) < 2)
                              return(1/length(x))
                          
                          index = selectindex(x:==max(x))
                          
                          return( index[runiformint(1,1,1,length(index))] )
                      }
                      Note that both selectindex() and runiformint() were introduced "recently", meaning Stata 16 or later; I don't recall exactly.
                      Last edited by daniel klein; 14 May 2025, 01:50. Reason: deleted second approach; too slow

                      Comment


                      • #12
                        Thank you Daniel!

                        As always, you come to the rescue with great Mata code!

                        I modified your code somewhat to include the additional extraction of the index value(s) from the original matrix (and reverted back to some of my original code). I should probably turn this into a Mata function rather than embed it into the Stata code... Please let me know if you see anything fatal here?

                        Code:
                        mat XX = (2,8,30,30,30,15,18,11,9)
                        
                        mata:
                          XX = st_matrix("XX")
                        
                          idx = selectindex(XX:==max(XX))'
                          rowscnt = rows(idx)
                          if (rowscnt > 1 ) idx = ( idx[runiformint(1,1,1,length(idx))] )
                        
                          st_local("idx", strofreal(idx))
                        end
                        
                        di `idx'

                        Comment


                        • #13
                          Here is a Mata function version if anyone is interested. Per Daniel's point about the version, it appears that runiformint() was introduced in v14 and selectindex()was introduced with in v15, thus I set this function to version 15.

                          Code:
                          version 15.0
                          mata:
                          mata clear
                          void function index_of_max(string scalar stata_matrixname)
                          
                          {
                              
                            XX = st_matrix(stata_matrixname)
                          
                            idx = selectindex(XX:==max(XX))'
                            rowscnt = rows(idx)
                            if (rowscnt > 1 ) idx = ( idx[runiformint(1,1,1,length(idx))] )
                          
                            st_local("idx", strofreal(idx))
                              
                          }    
                          
                          end
                          And to run it:

                          Code:
                          mat Q = (30,8,3,13,10,18,11,30)
                          mata: index_of_max("Q")
                          di `idx'

                          Comment

                          Working...
                          X