Announcement

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

  • How to refer to the local of a Mata for loop in a st_ function?

    How do you refer to the local i of the mata for loop in a st_ function such as st_numscalar? I tried a few things in the commented section below including st_numscalar("`A'i") but nothing worked, and I couldn't find an example or solution anywhere online.

    Code:
    tempname A1
    tempname A2
    tempname mat
    
    mata
    st_numscalar("`A1'", 4)
    st_numscalar("`A2'", 5)
    `mat' = J(2,1,0)
    
    // This for loop doesn't work to create a 1x2 matrix with A1 and A2 values
    for(i=1;i<=2;i++) {
        `mat'[i,1] = st_numscalar("`A'i")
    }
    `mat'
    end

  • #2
    The difficulty here is that the "i" in "`A'i" does not get translated to a string. Mata does not see "`A`'", but rather "i", since `A' is blank. i is not a local in Mata. (In fact, there are no "locals" in Mata.) i is a just a numeric variable to Mata. I don't know how to do what you are doing in the way that you want. I suspect you are wanting something that is more easily done in some other way, so giving a bit more context to your situation and goal would likely lead to a nicer solution.
    I'm confused also by why you would want to use Mata to put a number into a Stata scalar that you want to use as an element of a matrix in Mata. Do you really intend that these scalars exist in advance in Stata? In that case, I'd put those scalars into a Stata matrix, which is easy to access in Mata. This strengthens my thinking that you have a context that would lead us to suggesting a different approach.

    Comment


    • #3
      I agree with Mike Lacy.
      But for your described problem try the code

      Code:
      : st_numscalar("A1", 4)
      
      : st_numscalar("A2", 5)
      
      : `mat' = J(2,1,0)
      
      : for(i=1;i<=2;i++) `mat'[i,1] = st_numscalar(sprintf("A%f", i))
      
      : `mat'
             1
          +-----+
        1 |  4  |
        2 |  5  |
          +-----+
      Kind regards

      nhb

      Comment


      • #4
        Neils, I hadn't used sprintf() before; that's interesting. But there's still a wrinkle here: The Mata code you provide is using the non-temporary scalars A1 and A2, but Cyrus wants to use the temp-named scalars `A1' and `A2'. I'm curious: Can you work that in here?

        Comment


        • #5
          Just as Mike said, Niels' solution works for creating non-temporary scalars, but I could not convert that code to create temp-named scalars such as `A1'. This and various other things don't work:
          Code:
          `mat'[i,1] = st_numscalar(sprintf("`A%f'",i))
          Is there a way to get temp-named scalars by this work around?

          To answer Mike's original question, the reason why I switch back and forth between Stata and Mata is because I have a complicated regression methodology program and the way I programmed it, there is a need to use both Stata and Mata. The program was originally all in Stata, but introducing Mata provided substantial speed advantages. So I started converting some parts of the Stata program into Mata. The temp-name scalars part is one of those part that I thought could be easily converted to Mata. But I realize it is probably not that easy. The problem, as you mentioned, is how to use the i of the Mata for-loop as a string. So in its simplest form while you can do the following in Stata to create a million of scalars named A1, A2, A3 and so on:
          Code:
          forvalues i=1/1000000 {
          scalar A`i'=`i'
          }
          scalar dir
          You cannot do something like the following in Mata to create a million of scalars named A1, A2, A3 and so on in pure Mata:
          Code:
          mata
          for(i=1;i<=1000000;i++) {
          A`i' = i
          }
          end
          I hear you saying "why don't you create a matrix instead" but does that mean it is really not possible in Mata to write the code above in a "clean" fashion to get what it really aims for without the need to use sprintf or other functions? For my original question, it would still be somewhat sufficient to get temp-named scalars with a work around such as Niels' but is it really possible?

          Comment


          • #6
            Is this what you want?
            Code:
            : x = st_tempname(2)
            
            : st_numscalar(x[1], 4)
            
            : st_numscalar(x[2], 5)
            
            : x
                          1          2
                +-----------------------+
              1 |  __000006   __000007  |
                +-----------------------+
            
            : `mat' = J(2,1,0)
            
            : 
            : for(i=1;i<=2;i++) `mat'[i,1] = st_numscalar(x[i])
            
            : `mat'
                   1
                +-----+
              1 |  4  |
              2 |  5  |
                +-----+
            Kind regards

            nhb

            Comment


            • #7
              Niels, this is close but now I am not sure how to refer to these scalars back in Stata. When you create a temporary x in Mata as in your code, and then return to Stata, the scalars aren't listed in the available macros. It seems like they become "nameless" scalars. How do you access them in Stata?

              Code:
              mata
              x = st_tempname(2)
              st_numscalar(x[1], 4)
              st_numscalar(x[2], 5)
              x
              mat = J(2,1,0)
              for(i=1;i<=2;i++) mat[i,1] = st_numscalar(x[i])
              mat
              end
              
              tempname temps
              scalar `temps'=5
              scalar list `temps'
              scalar dir
              macro dir //there isn't anything about x in here such as _x but _temps is there
              scalar list `x[1]' //so this doesn't work
              scalar list `x' //this neither
              scalar list __00000M //this works but notice that it's not the name of it, and cannot be used


              Comment


              • #8
                This might be what you want:
                Code:
                . mata x = st_tempname()
                . mata st_local("tmpname", x)
                . scalar `tmpname' = 4
                . mata st_numscalar(x)
                  4
                Kind regards

                nhb

                Comment


                • #9
                  This works for a single tempname, but then how to name hundreds of them in a Mata loop is my original question really: Converting the number i of a for-loop in Mata to a piece of string to name a tempname.

                  Code:
                  mata x = st_tempname(100)
                  
                  for(i=1;i<=100,i++) {
                  mata st_local("tmpname1", x[1])
                  mata st_local("tmpname2", x[2])
                  // ... How to write this loop with i is the problem. x[i] works for sure but ...
                  // is there really a way in mata to create "tmpname`i'" strings based on for-loop number i?
                  mata st_local("tmpname100", x[100])
                  }

                  Comment


                  • #10
                    You need to think out of the box
                    You do not define the temporary scalars in Stata, but in mata.
                    This way I think you have better control than in your setup.
                    Consider:
                    Code:
                    . mata
                    ------------------------------------------------- mata (type end to exit) ---------------------------------------------------------------------------------------------------------------------------------------------------------------
                    :         x = st_tempname(10)
                    
                    :
                    :         // Writing values in Mata
                    :         for(i=1;i<=10;i++) st_numscalar(x[i], i)
                    
                    :         // Reading values in Mata
                    :         for(i=1;i<=10;i++) st_numscalar(x[i])
                      1
                      2
                      3
                      4
                      5
                      6
                      7
                      8
                      9
                      10
                    
                    : end
                    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                    
                    .
                    . //writing in Stata
                    . forvalues i = 1/10 {
                      2.         mata st_local("tmpname", x[`i'])
                      3.         scalar `tmpname' = `i' + 10
                      4. }
                    
                    .
                    . //reading in Stata
                    . forvalues i = 1/10 {
                      2.          mata st_local("tmpname", x[`i'])
                      3.          di `tmpname'
                      4. }
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    I still think there must be a smarter way for your solution using eg mata functions
                    Kind regards

                    nhb

                    Comment


                    • #11
                      With the solution above you probably don't need the matrix `mat'.
                      Or you can have a tempname being a vector of tempnames:
                      Code:
                      tempname mat
                      mata `mat' = st_tempname(4)
                      Kind regards

                      nhb

                      Comment


                      • #12
                        Exactly! Thinking outside the box produced a solution! Thank you so much, Niels! You're so great! So, for all other people viewing this post, going back to the very first code that I posted, the solution is: when you need to use the i of a for-loop in Mata as a piece of string, instead of writing a Mata for-loop, wrap a Stata for-loop around your Mata code and use the `i' in your Mata lines. I agree that there may be a smarter way to do this, or perhaps a need to be able to do this purely in Mata, but for now, the solution looks like this:

                        Code:
                        tempname A1
                        tempname A2
                        tempname mat
                        
                        mata
                        st_numscalar("`A1'", 4)
                        st_numscalar("`A2'", 5)
                        `mat' = J(2,1,0)
                        end
                        
                        //instead of using a Mata for-loop, a Stata for-loop is used here to enable using for-loop's i as string
                        forvalues i=1/2 {
                            mata: `mat'[`i',1] = st_numscalar("`A`i''")
                        }
                        
                        mata `mat'

                        Comment

                        Working...
                        X