Announcement

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

  • Confusion about compound quotes

    I am having a problem with generating a string with quotes in it with a -forvalues- loop. I am using Stata/SE 17.0 for Windows.

    I want to create the labStrGoal string for a label in a graph via the -forvalues- loop for generalization purposes but get the error message:
    3" " invalid name
    r(198);



    . local LabStrGoal = `"1 "1/3" 2 "2/3" 3 "3/3" 4 "4/3""'

    . local LabStr = ""

    . forvalues n = 1 (1) 4 {
    2. local add = "`n'" + " " + `" "`n'/3" "' + " "
    3. local LabStr = "`LabStr'" + "`add'"
    4. display "`LabStr'"
    5. }
    3" " invalid name
    r(198);


    What should I change in the code?

    Thanks in advance for your consideration.

    Marnix

  • #2
    Working with quotes in macros can get very confusing very quickly. Initial and final quotes provided in a macro definition are stripped, so that things internally are often not what you might think they are based on what you see in the code.

    In this case, I think the best way to build this final result is to first build it without any quotes, and then supply the quotes at the very end:

    Code:
    local LabStr
    
    forvalues n = 1 (1) 4 {
         local LabStr `LabStr' `n'
         local LabStr `LabStr' `n'/3
         display "`LabStr'"
    }
    
    local LabStr: subinstr local LabStr " " `"" ""', all
    local LabStr `""`LabStr'""'
    display `"`LabStr'"'

    Comment


    • #3
      Thank you very much Clyde for your help. However, the result from your code is slightly different from what I am after. If I define the string I want to generate without the loop it looks like:

      . local LabStrGoal = `"1 "1/3" 2 "2/3" 3 "3/3" 4 "4/3""'
      . display `"`LabStrGoal'"'
      1 "1/3" 2 "2/3" 3 "3/3" 4 "4/3"


      I want to use that string as a label for an x-axis in a graph so (as far as I know) it is important that the structure is like that.

      The result of your code is:
      . display `"`LabStr'"'
      1" "1/3" "2" "2/3" "3" "3/3" "4" "4/3


      I am trying myself with the code you proposed to change it, but did not manage.

      Thanks in advance for your help!

      Comment


      • #4
        Let's go back to the original problem.

        You want text for labelling the axis of a variable. You can do that directly, with something like

        Code:
        ...  xla(1 "1/3" 2 "2/3" 3 "3/3" 4 "4/3")

        Or you can do it programmatically by defining value labels which you will ask for in a graph, or which will appear automagically.

        Code:
         forval j = 1/4 {
            label define foo `j' "`j'/3", add
        }
        
        label li foo
        foo:
                   1 1/3
                   2 2/3
                   3 3/3
                   4 4/3
        I agree with @Clyde Schechter: compound double quotes can get confusing very quickly, and that doesn't stop even with much experience. Hence I always prefer ways of avoiding them.

        I guess the thinking behind #1 was

        1. I need to give label define a definition with several strings.

        2. So I need to loop compiling the definition before I call up label define.

        But the add and modify options give you another way to do it.

        Comment


        • #5
          Thank you very much Nick, this code does indeed exactly what I am after. I wasn't aware of this way of building labels in a loop.

          Comment


          • #6
            ref #1 and #2:
            Code:
            forvalues n = 1/4 {
                
                 local LabStr `LabStr' `n' "`n'/3"     
            }
            
            tw scatteri 1 1 , xlab(`LabStr') 
            
            macro list _LabStr // show local as is  
            
            gr describe 
            display `"`r(command)'"' // compound double quotes needed

            Comment


            • #7
              Re #3:
              The result of your code is:
              . display `"`LabStr'"'
              1" "1/3" "2" "2/3" "3" "3/3" "4" "4/3
              That's not what I get on my system:
              Code:
              . local LabStr
              
              .
              . forvalues n = 1 (1) 4 {
                2.      local LabStr `LabStr' `n'
                3.      local LabStr `LabStr' `n'/3
                4.      display "`LabStr'"
                5. }
              1 1/3
              1 1/3 2 2/3
              1 1/3 2 2/3 3 3/3
              1 1/3 2 2/3 3 3/3 4 4/3
              
              .
              . local LabStr: subinstr local LabStr " " `"" ""', all
              
              . local LabStr `""`LabStr'""'
              
              . display `"`LabStr'"'
              "1" "1/3" "2" "2/3" "3" "3/3" "4" "4/3"
              Another thing to be aware of is that when -display- displays macros, it sometimes makes cosmetic adjustments like stripping outer quotes. That may have happened on your system, so that what you are seeing with -display- is not what Stata actually stores internally (and would use when you invoke the local macro elsewhere in your code). To see what Stata actually stores, with no cosmetic adjustments
              Code:
              . macro list _LabStr
              _LabStr:        "1" "1/3" "2" "2/3" "3" "3/3" "4" "4/3"

              Comment

              Working...
              X