Announcement

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

  • Combining graphs from a loop

    Hi,
    I am making histograms using the following command that I want to loop for 122 countries,

    Code:
    twoway (histogram stunting if Residence==1, color(red%30) disc freq) (histogram stunting if Residence==2, color(green%10) disc freq)
    and then merge them using this, but it is not working. Can you please help detect the error in this approach:

    Code:
    levelsof country, local(levels)
    
    foreach l of local levels{
    
    qui twoway (histogram stunting if Residence==1, color(red%30) disc freq) (histogram stunting if Residence==2, color(green%10) disc freq)
     local graphnames `country'
    }
    
    graph combine  `country', row(4)

    It shows the following error:
    Code:
    . graph combine  `graphnames'
    unrecognized command
    r(199);

    Thank you in advance.

  • #2
    So, there are a few separate things going wrong here.

    With regard to the unrecognized command error, this is almost surely a typographical problem related to non-printing characters contaminating your code. I'm guessing that you copied this code (or at least that line of it) from some other electronic source. Perhaps a word processing document, or even from this Forum. When you do that, sometimes you pick up non-printing characters that, by definition, you do not see with your eye, but which are there. They're there to provide formatting information to whatever application contains that text. The problem is that even though we don't see them with our eyes, Stata "sees" them. And they are not part of any legal command name. My suggestion is to completely delete that line (the entire line, not just what you can see!) from your code and hand-retype it fresh. That should make that error message go away.

    But your code still won't work. That's because local macro graphnames will contain nothing. Notice that you never actually put anything in it. You have tried to, with the command -local graphnames `country'-. But local macro country is, itself, undefined. That is not hard to fix. But even then, the code will still not work, because graphnames will contain the names of the countries, but -graph combine- requires the names of stored graphs, and you have not named and stored any of the graphs your loop creates. Here's a fix for all of that:

    Code:
    levelsof country, local(levels)
    local graphname
    
    
    foreach l of local levels{
    
    qui twoway (histogram stunting if Residence==1, color(red%30) disc freq) ///
        (histogram stunting if Residence==2, color(green%10) disc freq) name(country`l', replace)
     local graphnames `graphnames'  country`l'
    }
    
    graph combine `graphnames'
    But this won't work as you expect it to, either. Notice that your -twoway- command makes no mention at all of the iterator `l'. So it's just plotting the same graph over and over again and you will get a bunch of copies of it. As I don't know exactly how you want these graphs to depend on the particular country, I can't fix that for you. At a minimum I would imagine that -if country == `l'- plays a role there. And I also imagine that you might want to put `l' somewhere on the graph, perhaps in a title or note. Again, you'll have to make that decision.

    Finally, one more potential pitfall. Is country a numeric or string variable? The above code assumes it's numeric--because that makes the code as simple as possible. But if it's a string variable then, at a minimum, you have three concerns:

    1. Are all the values of country legal names for a graph (the rules are the same as names for Stata variables)? If not, you may have to purge embedded blanks or otherwise clean them up. Check out the -strtoname()- function for that purpose.
    2. In this case, I would replace country`l' with just `l' in both places.
    3. If you end up using -if country == `l'- type logic (or something similar), it will have to be -if country == `"`l'"'- instead.

    Finally, though it's neither a Stata issue, nor, strictly speaking, a statistical one, I recommend not relying solely on red/green to distinguish the two histograms on the graph: 10% of males are color blind and cannot differentiate them. If you use red and green, also change the fill pattern or overlay some text in a way that a color blind person can tell which is which.
    Last edited by Clyde Schechter; 03 Feb 2022, 17:58.

    Comment


    • #3
      Originally posted by Clyde Schechter View Post
      So, there are a few separate things going wrong here.

      With regard to the unrecognized command error, this is almost surely a typographical problem related to non-printing characters contaminating your code. I'm guessing that you copied this code (or at least that line of it) from some other electronic source. Perhaps a word processing document, or even from this Forum. When you do that, sometimes you pick up non-printing characters that, by definition, you do not see with your eye, but which are there. They're there to provide formatting information to whatever application contains that text. The problem is that even though we don't see them with our eyes, Stata "sees" them. And they are not part of any legal command name. My suggestion is to completely delete that line (the entire line, not just what you can see!) from your code and hand-retype it fresh. That should make that error message go away.

      But your code still won't work. That's because local macro graphnames will contain nothing. Notice that you never actually put anything in it. You have tried to, with the command -local graphnames `country'-. But local macro country is, itself, undefined. That is not hard to fix. But even then, the code will still not work, because graphnames will contain the names of the countries, but -graph combine- requires the names of stored graphs, and you have not named and stored any of the graphs your loop creates. Here's a fix for all of that:

      Code:
      levelsof country, local(levels)
      local graphname
      
      
      foreach l of local levels{
      
      qui twoway (histogram stunting if Residence==1, color(red%30) disc freq) ///
      (histogram stunting if Residence==2, color(green%10) disc freq) name(country`l', replace)
      local graphnames `graphnames' country`l'
      }
      
      graph combine `graphnames'
      But this won't work as you expect it to, either. Notice that your -twoway- command makes no mention at all of the iterator `l'. So it's just plotting the same graph over and over again and you will get a bunch of copies of it. As I don't know exactly how you want these graphs to depend on the particular country, I can't fix that for you. At a minimum I would imagine that -if country == `l'- plays a role there. And I also imagine that you might want to put `l' somewhere on the graph, perhaps in a title or note. Again, you'll have to make that decision.

      Finally, one more potential pitfall. Is country a numeric or string variable? The above code assumes it's numeric--because that makes the code as simple as possible. But if it's a string variable then, at a minimum, you have three concerns:

      1. Are all the values of country legal names for a graph (the rules are the same as names for Stata variables)? If not, you may have to purge embedded blanks or otherwise clean them up. Check out the -strtoname()- function for that purpose.
      2. In this case, I would replace country`l' with just `l' in both places.
      3. If you end up using -if country == `l'- type logic (or something similar), it will have to be -if country == `"`l'"'- instead.

      Finally, though it's neither a Stata issue, nor, strictly speaking, a statistical one, I recommend not relying solely on red/green to distinguish the two histograms on the graph: 10% of males are color blind and cannot differentiate them. If you use red and green, also change the fill pattern or overlay some text in a way that a color blind person can tell which is which.
      Thanks so much Clyde! There is always so much to learn from your answers. I usually use the 'plottig' scheme as recommended for being colorblind-friendly. But I could not apply this here as it requires specifying the colors. I will try to find a solution for this.

      Regarding the potential errors that you suggested, I tried typing the code myself, and then used different variables (all numeric) instead of country. In all trials, I am getting the same error:

      Code:
      ) required
      r(100);

      Here is a portion of the data:

      ----------------------- copy starting from the next line -----------------------
      Code:
      * Example generated by -dataex-. To install: ssc install dataex
      clear
      input byte(Age Residence) int stunting long country
      5 1  184 1
      3 1  111 1
      1 1 -132 1
      2 1  -53 1
      1 1 -124 1
      5 1  -88 1
      4 1 -155 1
      4 1  -17 1
      7 1  172 1
      4 1  -72 1
      3 1    9 1
      6 1  150 1
      3 1   -3 1
      5 1  207 1
      6 1 -111 1
      3 1 -157 1
      4 1 -151 1
      4 1  -17 1
      5 1  -85 1
      5 1 -214 1
      6 1  -86 1
      7 1 -121 1
      4 1  109 1
      4 1  -69 1
      4 1  -31 1
      4 1  -42 1
      4 1  125 1
      5 1 -193 1
      6 1  -87 1
      4 1 -106 1
      4 1  -93 1
      4 1   72 1
      4 1  -29 1
      4 1  -89 1
      3 1  -64 1
      3 1 -232 1
      5 1  -40 1
      4 1  -20 1
      5 1 -110 1
      3 1  -24 1
      3 1   12 1
      5 1   62 1
      2 1  -60 1
      3 1 -114 1
      4 1  110 1
      4 1   20 1
      4 1 -192 1
      4 1  -57 1
      3 1 -233 1
      5 1  -66 1
      2 1 -192 1
      3 1  -47 1
      7 1  -69 1
      5 1  -26 1
      3 1  -14 1
      5 1  131 1
      3 1   93 1
      3 1    7 1
      6 1   19 1
      5 1  -17 1
      2 1  -72 1
      5 1 -104 1
      3 1 -125 1
      5 1  -89 1
      4 1  -62 1
      4 1  -36 1
      3 1  -33 1
      5 1  224 1
      3 1 -130 1
      3 1  -72 1
      2 1  -13 1
      3 1 -107 1
      3 1 -147 1
      4 1  -60 1
      3 1    1 1
      5 1   69 1
      1 1 -204 1
      5 1  -14 1
      3 1 -137 1
      3 1  -38 1
      2 1 -324 1
      6 1  -24 1
      3 1 -130 1
      4 1  -63 1
      3 1   64 1
      3 1 -142 1
      2 1  -94 1
      5 1   89 1
      3 1    2 1
      3 1 -192 1
      2 1  -63 1
      3 1 -105 1
      4 1   -5 1
      3 1 -146 1
      3 1  255 1
      2 1    9 1
      6 1 -134 1
      4 1 -117 1
      3 1  -17 1
      4 1   49 1
      end
      label values Age V013
      label def V013 1 "15-19", modify
      label def V013 2 "20-24", modify
      label def V013 3 "25-29", modify
      label def V013 4 "30-34", modify
      label def V013 5 "35-39", modify
      label def V013 6 "40-44", modify
      label def V013 7 "45-49", modify
      label values Residence V025
      label def V025 1 "urban", modify
      label values stunting HW5_1
      label values country cnn
      label def cnn 1 "GM7", modify



      Comment


      • #4
        Ah, that error message is actually misleading. The code has all the parentheses it needs. What's missing is a comma before name. Sorry about that.

        Code:
        qui twoway (histogram stunting if Residence==1, color(red%30) disc freq) ///
            (histogram stunting if Residence==2, color(green%10) disc freq), name(country`l', replace)
        local graphnames `graphnames' country`l'
        }

        Comment


        • #5
          Originally posted by Clyde Schechter View Post
          Ah, that error message is actually misleading. The code has all the parentheses it needs. What's missing is a comma before name. Sorry about that.

          Code:
          qui twoway (histogram stunting if Residence==1, color(red%30) disc freq) ///
          (histogram stunting if Residence==2, color(green%10) disc freq), name(country`l', replace)
          local graphnames `graphnames' country`l'
          }
          Thanks Clyde! It worked this time. It was a great lesson.

          I am attaching the sample graph, as there is something strange about the first (top left corner), it contains the axis labels that I want to avoid, as in the rest of the plots.

          Click image for larger version

Name:	Capture d’écran 2022-02-04 à 12.56.41.png
Views:	1
Size:	251.0 KB
ID:	1648456


          And this is the command:

          Code:
          levelsof country, local(levels)
          local graphname
           
          foreach l of local levels{
          qui twoway (histogram stunting if Residence==1, color(red%30) disc freq) (histogram stunting if Residence==2, color(green%10) disc freq), name(country`l', replace) legend(off) yla("") xla("")
           local graphnames `graphnames' country`l'
          }
          graph combine `graphnames'
          Is it possible to remove the legend and axis labels from the first plot.

          Comment


          • #6
            I can't see any reason why your code should cause that problem. The example data in #3 does not quite permit a full test of the code because it contains only one country and all values of Residence are 1. But when I modify and expand the data set to overcome those limitations and run your code with it, I do not get the problem you are encountering (see below). I don't know what to tell you.

            Code:
            * Example generated by -dataex-. To install: ssc install dataex
            clear
            input byte(Age Residence) int stunting long country
            5 1  184 1
            3 1  111 1
            1 1 -132 1
            2 1  -53 1
            1 1 -124 1
            5 1  -88 1
            4 1 -155 1
            4 1  -17 1
            7 1  172 1
            4 1  -72 1
            3 1    9 1
            6 1  150 1
            3 1   -3 1
            5 1  207 1
            6 1 -111 1
            3 1 -157 1
            4 1 -151 1
            4 1  -17 1
            5 1  -85 1
            5 1 -214 1
            6 1  -86 1
            7 1 -121 1
            4 1  109 1
            4 1  -69 1
            4 1  -31 1
            4 1  -42 1
            4 1  125 1
            5 1 -193 1
            6 1  -87 1
            4 1 -106 1
            4 1  -93 1
            4 1   72 1
            4 1  -29 1
            4 1  -89 1
            3 1  -64 1
            3 1 -232 1
            5 1  -40 1
            4 1  -20 1
            5 1 -110 1
            3 1  -24 1
            3 1   12 1
            5 1   62 1
            2 1  -60 1
            3 1 -114 1
            4 1  110 1
            4 1   20 1
            4 1 -192 1
            4 1  -57 1
            3 1 -233 1
            5 1  -66 1
            2 1 -192 1
            3 1  -47 1
            7 1  -69 1
            5 1  -26 1
            3 1  -14 1
            5 1  131 1
            3 1   93 1
            3 1    7 1
            6 1   19 1
            5 1  -17 1
            2 1  -72 1
            5 1 -104 1
            3 1 -125 1
            5 1  -89 1
            4 1  -62 1
            4 1  -36 1
            3 1  -33 1
            5 1  224 1
            3 1 -130 1
            3 1  -72 1
            2 1  -13 1
            3 1 -107 1
            3 1 -147 1
            4 1  -60 1
            3 1    1 1
            5 1   69 1
            1 1 -204 1
            5 1  -14 1
            3 1 -137 1
            3 1  -38 1
            2 1 -324 1
            6 1  -24 1
            3 1 -130 1
            4 1  -63 1
            3 1   64 1
            3 1 -142 1
            2 1  -94 1
            5 1   89 1
            3 1    2 1
            3 1 -192 1
            2 1  -63 1
            3 1 -105 1
            4 1   -5 1
            3 1 -146 1
            3 1  255 1
            2 1    9 1
            6 1 -134 1
            4 1 -117 1
            3 1  -17 1
            4 1   49 1
            end
            label values Age V013
            label def V013 1 "15-19", modify
            label def V013 2 "20-24", modify
            label def V013 3 "25-29", modify
            label def V013 4 "30-34", modify
            label def V013 5 "35-39", modify
            label def V013 6 "40-44", modify
            label def V013 7 "45-49", modify
            label values Residence V025
            label def V025 1 "urban", modify
            label values stunting HW5_1
            label values country cnn
            label def cnn 1 "GM7", modify
            
            //  MODIFY THE DATA SET TO INCLUDE RESIDENCE == 2 AND MULTIPLE COUNTRIES
            replace Residence = 2 if mod(_n, 2) == 0
            gen long obs_no = _n
            expand 10
            by obs_no, sort: replace country = _n
            drop obs_no
            
            
            levelsof country, local(levels)
            local graphname
             
            foreach l of local levels{
            qui twoway (histogram stunting if Residence==1, color(red%30) disc freq) ///
                (histogram stunting if Residence==2, color(green%10) disc freq), ///
                name(country`l', replace) legend(off) yla("") xla("")
             local graphnames `graphnames' country`l'
            }
            graph combine `graphnames'
            Click image for larger version

Name:	Sonnen_Blume.png
Views:	1
Size:	182.6 KB
ID:	1648462

            Comment


            • #7
              I am not following why graph combine is being used here rather than a by() option.


              Code:
              sysuse auto, clear 
              
              local opts start(10) width(2) fraction
              set scheme s1color 
              twoway histogram mpg if foreign== 0, `opts' color(red%20) || histogram mpg if foreign, `opts' color(blue%20) by(rep78, note("") legend(off))

              Comment


              • #8
                Originally posted by Nick Cox View Post
                I am not following why graph combine is being used here rather than a by() option.


                Code:
                sysuse auto, clear
                
                local opts start(10) width(2) fraction
                set scheme s1color
                twoway histogram mpg if foreign== 0, `opts' color(red%20) || histogram mpg if foreign, `opts' color(blue%20) by(rep78, note("") legend(off))
                Thank you Nick! This was super neat!!!

                Comment

                Working...
                X