Announcement

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

  • Sorting the columns of a matrix

    Dear Statalisters,
    I'm just getting started with Mata, so apologies upfront: I have, I think, a very simple question: I'm calculating eigenvectors and eigenvalues of square matrix Cmat. Here's an example for 3x3 matrix:

    Code:
    : Cmat = (2,2,3\1,2,2\1,2,0)
    
    :
    : // Eigenvalues and Eigenvectors
    : eigenvalues = .
    
    : eigenvectors = .
    
    :
    : eigensystem(Cmat, eigenvectors, eigenvalues,)
    
    
    : // Extract real part of eigenvalues and eigenvectors
    : eigenvectors = Re(eigenvectors)
    
    : eigenvalues = Re(eigenvalues')
    
    :
    :
    : eigenvectors
                      1              2              3
        +----------------------------------------------+
      1 |  -.7621332906   -.5136120346   -.8772027338  |
      2 |  -.5282854667   -.3152370696    .4686056046  |
      3 |  -.3742556787    .7980152053     .104518664  |
        +----------------------------------------------+
    
    : eigenvalues
                     1
        +---------------+
      1 |  4.859523389  |
      2 |  -1.43366463  |
      3 |  .5741412412  |
        +---------------+
    The eigenvectors are sorted by their absolute eigenvalues in descending order (the default), but I'd like to have the eigenvectors sorted by their actual eigenvalues, e.g.:

    Code:
    : sort(eigenvalues,-1)
                     1
        +---------------+
      1 |  4.859523389  |
      2 |  .5741412412  |
      3 |  -1.43366463  |
        +---------------+
    The first column of the eigenvector matrix should therefore represent the eigenvector with the largest value (4.86), the second column the eigenvector with the second largest value (.57) and so on.

    Thank you for your help!

    Best,
    Ali




  • #2
    PS: Here's my current workaround, which gets the job done, but feels a bit clumsy

    Code:
    : Re_sort=sort((eigenvalues' \ eigenvectors)',-1)
    :
    : ncols = cols(Re_sort)
    
    :
    : eigenvectors = (Re_sort[1..., 2..ncols])'
    
    :
    : eigenvectors
                      1              2              3
        +----------------------------------------------+
      1 |  -.7621332906   -.8772027338   -.5136120346  |
      2 |  -.5282854667    .4686056046   -.3152370696  |
      3 |  -.3742556787     .104518664    .7980152053  |
        +----------------------------------------------+

    Comment


    • #3
      If I understand your request, this may help

      Code:
      order = order(eigenvalues,-1)
      eigenvalues[order]
      eigenvectors[,order]

      Comment


      • #4
        Would this work in all cases?

        Code:
        mata:
            Cmat = (2,2,3\1,2,2\1,2,0)
            // Eigenvalues and Eigenvectors
            eigenvalues = .
            eigenvectors = .
            eigensystem(Cmat, eigenvectors, eigenvalues,)
            // Extract real part of eigenvalues and eigenvectors
            eigenvectors = Re(eigenvectors)
            eigenvalues = Re(eigenvalues')
            ev = eigenvectors'[order(eigenvalues,-1),.]'
            ev
        end

        Comment


        • #5
          Both suggestions work. Thanks Daniel and Scott!

          Best
          Ali

          Comment


          • #6
            Hi, when I sort a matrix, I would like to keep the original names of columns and rows. How can I do that?

            Example:

            I have the matrix A:
            TME PTME PC PRR
            Andalucia .15656199 .12322447 2.033e-06 1.2705429 .96197714
            Aragón .15951484 .12407515 1.779e-06 1.2856308 .95954026
            Asturias .16233983 .12742271 1.720e-06 1.2740259 .95998392
            Islas Bale~s .16614045 .13165379 1.666e-06 1.2619496 .96028466
            Canarias .15917927 .12188039 2.159e-06 1.3060285 .95752415
            Cantabria .16459393 .12626319 1.923e-06 1.3035782 .9561301
            Castilla-L~n .15245961 .11823103 1.836e-06 1.2895059 .96118192
            Castilla-L~a .15460907 .12151381 1.948e-06 1.2723581 .96232693
            Cataluña .17575781 .14004542 1.471e-06 1.2550058 .95847177
            Valenciana .16774078 .12685677 2.257e-06 1.3222849 .95317605
            Extremadura .16042142 .11391964 3.243e-06 1.4081982 .94751967
            Galicia .15425344 .11935986 1.923e-06 1.2923393 .96037703
            Madrid .15994971 .12654823 1.213e-06 1.2639427 .96175922
            Murcia .14988071 .11888892 1.805e-06 1.2606785 .96482648
            La Rioja .16039163 .12129363 2.036e-06 1.3223417 .95550505
            Ceuta y Me~a .16838468 .1297451 1.713e-06 1.2978115 .9555997
            Total Régi~n .16263953 .12735901 1.723e-06 1.2770163 .95957041

            I compute the following:

            mata: st_matrix("B", sort(st_matrix("A"), -1))

            The work is done, but I lost the original names of rows during the process. How can I avoid that? The names of the rows should be the same as the new order of the columns.

            Comment


            • #7
              Something along these lines should do:

              Code:
              A = st_matrix("A")
              rownames = st_matrixrowstripe("A")
              order = order(A, -1)
              st_matrix("B",A[order,])
              st_matrixrowstripe("B",rownames[order,])

              Comment

              Working...
              X