Announcement

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

  • Formatting value of a global macro when displayed in text - erroneous leading zero

    Hi, I'm using Stata 14.1 and trying to format the appearance of a global macro when I use the macro in a title for a graph. The global macro value is 1000, but when I use this in the title of my graph, I wish to display the text as 1,000 - with a comma separating the thousand. However while I can change the display to show the comma, I now have a leading zero in the text:

    Code:
    global rate = 1000
    
    di ${rate}
    1000
    
    di %5.0fc ${rate}
    1,000
    
    di as text "Incidence (per " di %5.0fc ${rate} " patients)"
    Incidence (per 01,000 patients)

    Does anyone know how I remove the zero from

    Incidence (per 01,000 patients)

    Thanks in advance
    Tim

  • #2
    When I run your code, Stata 15 for Mac throws an error on the final display command.
    Code:
    . global rate = 1000
    
    . di ${rate}
    1000
    
    . di %5.0fc ${rate}
    1,000
    
    . di as text "Incidence (per " di %5.0fc ${rate} " patients)"
    Incidence (per di not found
    r(111);
    Added in edit: When I remove the extraneous "di" from the final command I have
    Code:
    . di as text "Incidence (per " %5.0fc ${rate} " patients)"
    Incidence (per 1,000 patients)

    Comment


    • #3
      I cannot reproduce your problem on my setup, neither in Stata 14 nor Stata 15. What I do get frm your input is an error message because the di that appears between the close quote and the %5.0fc does not belong there. When you remove that, the following runs correctly in both Stata 14 and 15.

      Code:
      . global rate = 1000
      
      .
      . di ${rate}
      1000
      
      .
      . di %5.0fc ${rate}
      1,000
      
      .
      . di as text "Incidence (per " %5.0fc ${rate} " patients)"
      Incidence (per 1,000 patients)
      That said, you should not be doing this in the first place. The use of global macros is a dangerous programming practice and should be used only when there is no alternative. In this case, the alternative of a local macro is available and should be used. When you write -global rate = 1000-, you have no way to know whether some other program in memory, or some other program that will later come into memory, may also use a global macro named rate. When such a name clash occurs, your program and that one will be clobbering each other's crucial data and the bugs that result can be maddeningly difficult to fix. So the safe thing is simply not to use global macros except as a last resort, for situations where no other device will serve the purpose at hand. Use local macros instead, as their scope is, well, local, so you never have to worry about a name clash with another program.

      Added: Crossed with William's response, which, apart from my rant about global macros, says the same thing.

      Comment


      • #4
        Excellent - thanks, I have also now removed "di" from my example and it works for me now without the leading zero.
        Not sure what is going on between Mac and Windows, but in my Windows install of Stata 14.1, I never received the r(111) error you had.

        Comment


        • #5
          FWIW, I doubt the difference is Mac vs Windows, because I'm running Windows, and I'm pretty sure William Lisowski runs Mac and we both got the same thing.

          Comment


          • #6
            I can recreate Tim's problem. God bless the display command for working so hard to make sense of its arguments.
            Code:
            . global rate = 1000
            
            . scalar di = 0
            
            . di ${rate}
            1000
            
            . di %5.0fc ${rate}
            1,000
            
            . di as text "Incidence (per " di %5.0fc ${rate} " patients)"
            Incidence (per 01,000 patients)

            Comment


            • #7
              I'll share a screenshot to show I'm not going mad!

              I appreciate the comments regarding use of gobal macros, to mitigate this, I set them up in each specific do file and then close off each do file with

              Code:
              macro drop rate

              Comment


              • #8
                Thank you William Lisowski for chasing down the spurious zero!

                Comment


                • #9
                  I appreciate the comments regarding use of gobal macros, to mitigate this, I set them up in each specific do file and then close off each do file with

                  Code:
                  macro drop rate
                  Well, that's better than nothing. But there is no reason to do that. Apparently you want to define a parameter, rate, which you can set and use in each of several do files to get parallel results. You don't need global macros to do that.

                  First create a separate do-file, let's call it rate_define.do. It contains only this one command:
                  Code:
                  local rate 1000 // OR WHATEVER VALUE YOU PREFER
                  Now, in each of the other files where you were going to have -global rate = 1000-, scrap that and put this in its place:

                  Code:
                  include rate_define
                  The underused and under-appreciated -include- command causes the do-file named in it to be read in as part of the do-file* where the -include- command itself appears. Thus, it is as if you had -local rate = 1000- in each file. But if you later decide you prefer rates per 10,000, you can just change it in one place, rate_define.do, and all the other files will pick up the change automatically. No safety issues. And no need to worry about the possibility of forgetting to -macro drop rate-, as local macros go out of scope automatically when the do-file exits.

                  *In other words, it is not equivalent to saying -run rate_define- or -do rate_define-. With -include-, the actual text contained in rate_define.do becomes a part of the file that -include-s it.

                  Comment


                  • #10
                    It gets even better. Here's method 2 for reproducing Tim's problem, an even more impressive display of the display commands acumen.
                    Code:
                    . set obs 1
                    number of observations (_N) was 0, now 1
                    
                    . gen discover = 0
                    
                    . global rate = 1000
                    
                    . di ${rate}
                    1000
                    
                    . di %5.0fc ${rate}
                    1,000
                    
                    . di as text "Incidence (per " di %5.0fc ${rate} " patients)"
                    Incidence (per 01,000 patients)
                    I'm glad I pursued this because it reminds me that when I upgraded to Stata 15.0 I neglected to set varabbrev off as I had in Stata 14 and Stata 13.

                    Comment


                    • #11
                      Clyde Schechter - thanks for suggestion here - I'll take a look into modifying my code to reflect your comments. The main reason I started with the global macro is that I am running two sets of analysis in two different do files. One is for prevalence of a disease, for which in the main I wish to set the macro value to 100 - so that I can report a prevalence percent. For incidence, I wanted to be able to vary the ${rate} as some diseases are quite rare and I needed to vary the ${rate} in order to assess which was the appropriate rate to report at - meaning I could easily vary the rate without much change to my overall code - but I'll take your advice that there is a better way.

                      I'll now reveal the true problem I have now - I thought I would develop the code using the 'di as text' and then drop into a ytitle section of my chart as shown below:
                      Code:
                       use http://www.stata-press.com/data/r13/diet, clear
                      stset dox, origin(time doe) id(id) scale(365.25) fail(fail==1 3 13)
                      stsplit ageband, at(40(10)70) after(time=dob) trim
                      
                      
                       #delim ;
                        strate ageband, per(${rate})
                        output("incOf_age10_per${rate}", replace)
                        graph name("incidence", replace)
                        title("crude incidence by 10 year age group)", size(medium))
                        xtitle("10 year age band", size(medsmall))
                        ytitle("Incidence (per " %5.0fc ${rate}, height(10) size(medsmall))
                        xlabel(0 40(10)60, angle(vertical) labsize(medsmall))
                        ylabel(0.0(2)18, format(%5.0f) angle(h) labsize(medsmall))
                        plotregion(color(white))
                        saving("incOf_age10_per${rate}", replace) ;
                       #delim cr
                      However what I get now is "Incidence (per %5.0fc 1000)

                      I'm not sure what to change in the line

                      Code:
                      ytitle("Incidence (per " %5.0fc ${rate}, height(10) size(medsmall))

                      Comment


                      • #12
                        I believe what you want is:
                        Code:
                        ytitle("Incidence (per " `:display %5.0fc ${rate}', height(10) size(medsmall))

                        Comment


                        • #13
                          Here's one approach.
                          Code:
                          . global rate 1000
                          
                          . local yt `"Incidence (per `=strofreal(${rate},"%5.0fc")')"'
                          
                          . display `"ytitle(`"`yt'"', height(10) size(medsmall))"'
                          ytitle(`"Incidence (per 1,000)"', height(10) size(medsmall))

                          Comment


                          • #14
                            Thanks for the help. I just needed to just add quote marks either side of your suggestion:
                            Code:
                             ytitle("Incidence (per " "`:display %5.0fc ${rate}')", height(10) size(medsmall))
                            This now works as I hoped for:

                            Code:
                            global rate= 1000
                            use http://www.stata-press.com/data/r13/diet, clear
                            stset dox, origin(time doe) id(id) scale(365.25) fail(fail==1 3 13)
                            stsplit ageband, at(40(10)70) after(time=dob) trim
                            
                             #delim ;
                              strate ageband, per(${rate})
                              output("incOf_age10_per${rate}", replace)
                              graph name("incidence", replace)
                              title("crude incidence by 10 year age group)", size(medium))
                              xtitle("10 year age band", size(medsmall))
                              ytitle("Incidence (per " "`:display %5.0fc ${rate}')", height(10) size(medsmall))
                              xlabel(0 40(10)60, angle(vertical) labsize(medsmall))
                              ylabel(0.0(2)18, format(%5.0f) angle(h) labsize(medsmall))
                              plotregion(color(white))
                              saving("incOf_age10_per${rate}", replace) ;
                             #delim cr
                            
                            macro drop rate
                            Last edited by Tim Evans; 13 Jul 2017, 16:33.

                            Comment


                            • #15
                              Yes, of course, the external quote marks are needed there. Sorry I forgot those.

                              Comment

                              Working...
                              X