Announcement

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

  • Can Stata evaluate expressions on the fly?

    I have the following little loop that works. Before creating the macro var "curvar" (which works in the next expression to add a label to a variable), I was trying to add the -word("`symbol'", `j')- to the label command [label var word("`symbol'", `j') "`I'"] and getting all kinds of syntax errors.

    Is it possible in Stata to evaluate such expressions as the word() function within the code without having to create the macro var? In some coding languages there are functions such as eval(), etc. that can evaluate the expression within the code. I was wondering if such a thing exists in Stata.

    *put labels on vars
    local j=0
    foreach i in "`lblnam'" {
    local ++j
    local curvar=word("`symbol'",`j')
    label var `curvar' "`i'"
    }

  • #2
    You can force the evaluation using macro quotes and a leading equal sign.

    Code:
    `=word("`symbol'", `j')'

    Comment


    • #3
      My guess is that the problem in #1 would be much easier to address if we had much more context and a reproducible example.

      Comment


      • #4
        Thanks. The nine items in "symbol" are the var names in the dataset. The 9 items in "lblnam" are the labels to be added to the cryptic var names in the same orders. The dataset contains these var names with historical price data for each. I'm just adding labels to easily explain the short, cryptic var names. Previous loops in the code create the vars and populate them with the historical data. I'm adding the labels after the dataset is created because I didn't think about it when creating the vars. Let me know if you need additional data.

        I'm trying to set up the code for these products because I have more sets of products that I'm hoping to be able to use the same code with changes only in product names.

        local symbol aud gbp brl cad chf eur jpy mxn nzd
        local lblnam "Australian Dollar" "British Pound Sterling" "Brazilian Real" "Canadian Dollar" "Swiss Franc" "Euro" "Japanese Yen" "Mexican Peso" "New Zealand Dollar"

        *put labels on vars
        local j=0
        foreach i in "`lblnam'" {
        local ++j
        local curvar=word("`symbol'",`j')
        label var `curvar' "`i'"
        }

        Comment


        • #5
          Thanks much for the detail.

          There's no disgrace in just writing out 6 command lines such as

          Code:
          label var aud "Australian dollar"
          as that is less code, much easier for most readers to grasp, and easier too for the programmer to write and maintain.

          I would say the same for 60 currencies even!

          Looping in your case is about as tricky as possible given a problem simple in principle. One challenge is a need to wrestle with compound double quotes too, unless I am missing something. .

          I got this to work:

          Code:
          clear 
          set obs 1 
          
          local symbol aud gbp brl cad chf eur jpy mxn nzd
          tokenize `" "Australian Dollar" "British Pound Sterling" "Brazilian Real" "Canadian Dollar" "Swiss Franc" "Euro" "Japanese Yen" "Mexican Peso" "New Zealand Dollar" "'
          
          local j = 1 
          foreach v of local symbol { 
              gen `v' = 42 
              label var `v' `"``j''"'
              local ++j 
          }
          
          describe
          Code:
          . describe 
          
          Contains data
           Observations:             1                  
              Variables:             9                  
          ---------------------------------------------------------------------------------------
          Variable      Storage   Display    Value
              name         type    format    label      Variable label
          ---------------------------------------------------------------------------------------
          aud             float   %9.0g                 Australian Dollar
          gbp             float   %9.0g                 British Pound Sterling
          brl             float   %9.0g                 Brazilian Real
          cad             float   %9.0g                 Canadian Dollar
          chf             float   %9.0g                 Swiss Franc
          eur             float   %9.0g                 Euro
          jpy             float   %9.0g                 Japanese Yen
          mxn             float   %9.0g                 Mexican Peso
          nzd             float   %9.0g                 New Zealand Dollar
          ---------------------------------------------------------------------------------------
          Sorted by: 
               Note: Dataset has changed since last saved.
          More discussion at https://journals.sagepub.com/doi/pdf...6867X211063415

          Comment


          • #6
            Naturally there are 8 currencies in the problem, not 6.

            Here is another way to do it. Clearly I need to generate variables; otherwise I can't assign variable labels. But in your case they already exist.

            The paper linked in #2 remains germane.

            Code:
            clear 
            set obs 1 
            
            local symbol aud gbp brl cad chf eur jpy mxn nzd
            local labnam `" "Australian Dollar" "British Pound Sterling" "Brazilian Real" "Canadian Dollar" "Swiss Franc" "Euro" "Japanese Yen" "Mexican Peso" "New Zealand Dollar" "'
            local nv : word count `symbol'
            
            forval j = 1/`nv'  { 
                gettoken v symbol : symbol
                gen `v' = 42 
                gettoken lbl labnam : labnam 
                label var `v' `"`lbl'"'
            }

            Comment


            • #7
              Andrew Musau thanks. Yes, that seems to work to resolve the expression within the code.

              Comment


              • #8
                Nick Cox, yes that method works. I've had to look up some of those commands as I've only used Stata for about a month (hence, my monitoring of this forum). But, I've coded in SAS and recently Python for many years. I'm retired so no one will be using my code except me, so I am only concerned about its readability and documentation to satisfy my need to remember what things are doing. The tokenize command and subsequent references are interesting. I see the command:
                label var `v' `"``j''"' to be interesting. If I understand correctly, the 2 macro quotes around j makes it resolve j first as a numeric, then second it resolves the numeric macro var that is created by the "tokenize" command. If you don't mind me asking, I see in several places that you put macro quotes (` and ') on the "outside" of the double quotes. It seems to me it works fine without those outside macro quotes. What is the point of using those outside macro quotes? As mentioned, I'm on a steep learning curve with Stata coding methods and commands.

                Comment


                • #9
                  I see in several places that you put macro quotes (` and ') on the "outside" of the double quotes. It seems to me it works fine without those outside macro quotes. What is the point of using those outside macro quotes?
                  The configuration `" whatever "' is called compound double quotes. You can read about them in the Users Guid section of the PDF documentation that is installed with your Stata. They exist, and should be used, whenever whatever might, itself, contain quotation marks. The problem with ordinary quotation marks is that if you have something like "abc"def"ghi", it isn't clear whether you are quoting abc, then listing def, and then quoting ghi, or if you are quoting abc"def"ghi. That's because unlike parentheses, brackets, and braces, the opening delimiter and the closing delimiter of quotation marks are exactly the same. Yes, in some software, there are "smart quotes" where an opening quotation mark looks like a little 99 and the closing one looks like a little 66. But Stata doesn't have those. And if you try to nest a quotation inside of a quotation, Stata will get very confused. Compound double quotes were meant to solve this problem: `" does not look the same as "'. So Stata can easily distinguish `"abc"'def`"ghi"', two quoted strings surrounding an unquoted one, from `"abc`"def"'ghi"', where quoted def is nested inside quoted abc...ghi.

                  If you are just using strings like "yes", "no", "John", etc., and you won't be nesting quotes inside quotes, then you do not need to use compound double quotes: the ordinary quotes work just fine. But when you are writing code and you are putting quotes around macros, e.g. in `"`x'"', if there is any possibility that the content of `x' can contain quotes, it is safer to use the compound double quotes.
                  Last edited by Clyde Schechter; Yesterday, 18:59.

                  Comment


                  • #10
                    So, in any given list or expression, I should use `" in front and '" in back? assuming that there is a possibility of "quotes inside? Or, even if there are no " quotes, then it would do no harm?

                    Comment


                    • #11
                      That is correct. You will never go wrong by using `" "'.

                      The motivation for sometimes using simply " " when you are certain that the material contained within cannot contain quotation marks is simply that it is easier on the human eye. It makes the code more readable to people. While human readability of code is important, it should never trump having the code work correctly. " " will not work correctly (and typically won't work at all) when there are quotes internal to the quoted material.

                      Comment


                      • #12
                        Some of the details in #8 were covered in the previously linked https://journals.sagepub.com/doi/pdf...6867X211063415

                        You did a good job of working out what stuff like

                        Code:
                        ``j''
                        means, which was explained there.

                        Here is a footnote to Clyde Schechter 's careful explanation.

                        A detail that can bite very hard that programmers need to keep remembering is that in defining macros any outermost quotation marks are treated as delimiters and so stripped on assignment of contents to the macro. We can be casual in that

                        Code:
                        local foo frog 
                        
                        local foo "frog"
                        will both work to assign the text frog to the local macro foo. But in writing

                        .
                        Code:
                         local lblnam "Australian Dollar" "British Pound Sterling" "Brazilian Real" "Canadian Dollar" "Swiss Franc" "Euro" "Japanese Yen" "Mexican Peso" "New Zealand Dollar"
                        you were unwittingly bitten. The result can be seen quickly with this command (where I omit output I got that is irrelevant to the question)

                        Code:
                         
                        . mac li
                        
                        _lblnam:        Australian Dollar" "British Pound Sterling" "Brazilian Real" "Canadian
                                        Dollar" "Swiss Franc" "Euro" "Japanese Yen" "Mexican Peso" "New Zealand
                                        Dollar
                        Arghhh! as they used to say in comic books when I read them. By accident you've lost the outermost quotation marks you really needed. So the first token (word) of what remains is not "Australian Dollar" but just Australian and that is not the result you want here.

                        I think of the compound double quotes you must add as a deliberate but fortunately painless sacrifice to ensure that the double quotation marks inside get through to the next step.

                        I will bet that this slip was the source of various syntax errors alluded to but not cited in #1.

                        Comment

                        Working...
                        X