Announcement

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

  • Changing the colour of individual markers in twoway scatter graph

    Hello

    Specifically I am using serrbar which I understand has the same options as graph twoway. I have 150 cases for the x axis, but these are grouped, so that I want marker #1 to be black, #2 dark grey, #3 medium grey, #4 light grey, #5 white. I then want to repeat this colouring across all 150 cases. I can do this manually with the graph editor, but I have to produce many graphs, so would it would take an inordinate amount of time. Is there a way to do this either? 1. Manually specifying a colour for each marker 2. Generating a variable that runs 1-5 across the the 150 cases, then using this to specify the colours of all the 1s, 2s, 3s, etc.? The second option sounds like less work but I'll happily take either.

    Many thanks
    Dan

  • #2
    As per forum etiquette, I am bumping once, and politely!

    Comment


    • #3
      Read through FAQ Advice #12 to increase your chances of making progress. The burden of reproducing the problem should be on your part, not on those you seek help from.

      Comment


      • #4
        Thanks for your reply. I had considered posting code and pictures but I'm not sure what it would add. It seems a very straightforward problem to me - I simply want to colour individual markers in a graph.

        Comment


        • #5
          Andrew Musau is right here. This may seem a simple question but it would be much easier to answer concretely with a data example, including variable names. I saw this question when posted and moved on, as did several others.

          The underlying principle is that Stata will happily show markers in different colours -- so long as you specify different variables. There could be, but there usually isn't, an option to assign different colours to different groups of observations. If there is such an option, inside a command, different variables are being generated temporarily for the different marker colours.

          serrbar is a very old command going way back. My guess is that it originated because a user asked for something simple and it seemed easy and reasonable enough to fold that back into official Stata. I am documented as the author which is both welcome and embarrassing. My role (in Stata 6) was just to modify the then command to be a little more general. But I've had nothing to do with it ever since and don't even use it. It's a StataCorp rule that program code is never explained as written by particular StataCorp authors. For some commands, that would mean a very long list, although more commands than you might guess come from one or two people.

          serrbar just does what it does, which is always true, but in this case it isn't much. It isn't, and can't possibly be, a general command for showing error bars or more generally any kind of uncertainty interval. The range of graphics under that heading is just about as wide as the range of graphics generally. Do the indications of uncertainty exist already or are they to be calculated by the command? How do you want to show the intervals? Do you want to show data as well and if so how? Do you have several variables and/or several groups?

          Undoubtedly you have a simple graphical request but my guess is that it's best accommodated directly through
          twoway. I could write a much longer answer sketching various possibilities, but better yet would be a precise data example.

          Comment


          • #6
            Hi Nick

            Thank you for your response. As you might be aware, serrbar is often suggested by multilevel modelling texts as a quick and easy way to produce catterpillar plots of level two estimates. So in my case, I am running a mlm, generating predicted level 2 coefficients and their standard errors and using these two variables to create the plot.

            Code:
            serrbar intersections4_crp_50 intersections4_crp_se_50 order, scale(1.96) xtitle(Women                                            Men, margin(medium))  ytitle (mg/L) ylabel(, ang(90)) title("C-reactive protein, age 50-59") scheme(plottig) yscale(range(0 5)) ylabel(0(0.5)5) xlabel(0 15.5 30.5 45.5 60.5 75.5 90.5 105.5 120.5 135.5 150.5, nolabel notick) xmlabel(7.5 "White British" 22.5 "Chinese" 37.5 "Indian" 52.5 "Pakistani" 67.5 "Caribbean" 83 "White British" 98 "Chinese" 113 "Indian" 128 "Pakistani" 143 "Caribbean", nogrid notick angle(0)) cmissing(y) xline(75.5, lstyle(foreground))
            graph export crp_50_equal.tif, replace
            This generates the image below.

            Just to briefly explain the variables, intersections4_crp_50 are the level 2 predicted effects, intersections4_crp_se_50 are the standard errors of those effects. There are 150 groupings at level2. The x labels describe the level2s, which are 'intersections' i.e. combinations of socio-demographic factors. As you can see, I can use these to show gender and age. And I also need to add education, which I can easily do manually. This goes as follows - intersections 1-5 = low education, 6-10 = medium, 11-15 = high, which then repeats across all gender x ethnicity groupings. However then, it becomes complex to add the other grouping variable which is deprivation. This runs from very low (1) to very high (5), and then repeats within levels of education i.e. very low (6), very high (10), 11, 15 etc.. So, instead of adding labels for this, my idea was to shade all marker 1, 6, 11 etc as e.g. very dark grey, 2, 7, 12 etc. as medium grey, and so on and so forth, and then add a legend to the graph to show this.

            I would be extremely grateful if you have any insight into how this might be achieved. And noted for next time regarding the posting format - I'll make no assumptions about what constitutes a simple problem!

            Regards
            Dan

            This produces the following graph:
            Click image for larger version

Name:	crp_50.tif
Views:	1
Size:	38.0 KB
ID:	1565899

            Comment


            • #7
              #6 still does not constitute a reproducible example. You need to additionally include a data example using the dataex command. All of this is explained in FAQ Advice #12.

              Edit: Nick Cox has been generous enough to provide a solution in #8, but keep in mind these issues for future posts,
              Last edited by Andrew Musau; 29 Jul 2020, 09:46.

              Comment


              • #8
                Here is a basic example showing how to get different colours on an equivalent of serrbar.

                Code:
                webuse assembly, clear 
                separate mean, by(date) veryshortlabel
                local means `r(varlist)'
                gen upper = mean + std 
                gen lower = mean - std 
                separate upper, by(date) veryshortlabel
                separate lower, by(date) veryshortlabel 
                
                local colours black blue orange magenta red pink teal 
                
                levelsof date, local(DATES)
                
                local call 
                local j = 1 
                foreach D of local DATES { 
                    local thiscolour : word `j' of `colours'  
                    local call `call' || rcap upper`D' lower`D' date, lc(`thiscolour') 
                    local ++j 
                }
                
                twoway `call' || scatter `means'  date, mc(`colours') legend(off) scheme(s1color) xla(`DATES')

                Comment


                • #9
                  Hi Nick, brilliant, thanks for taking the time to write the example. I will work through it and to adapt to my own graph.
                  BW Dan.

                  Comment


                  • #10
                    Hi Nick, just to update. This works great for the first 20 data points, which I colour by repeating the first 5, as my variables are grouped in fives (with 150 in total):
                    Code:
                     local colours black blue orange magenta red black blue orange magenta red black blue orange magenta red black blue orange magenta red
                    However, when I try to repeat beyond this I get the error:

                    p21(marker(fillcolor(black) linestyle(color(black)))): too many arguments
                    r(103);

                    It seems this is an inherent limitation of twoway. Any advice greatly appreciated (I haven't used macros before, so it's quite difficult to work out how I might even begin with this).

                    Many thanks
                    Dan
                    Last edited by Dan Holman; 29 Jul 2020, 15:11. Reason: typo

                    Comment


                    • #11
                      Just add add the full (modified) code, in case useful:

                      Code:
                      gen upper = intersections4_hba1c_40 + intersections4_hba1c_se_40 
                      gen lower = intersections4_hba1c_40 - intersections4_hba1c_se_40 
                      separate upper, by(intersections4) veryshortlabel
                      separate lower, by(intersections4) veryshortlabel 
                      
                      local colours black blue orange magenta red black blue orange magenta red black blue orange magenta red black blue orange magenta red
                      
                      levelsof intersections4, local(INTERSECTIONS4)
                      
                      local call 
                      local j = 1 
                      foreach D of local INTERSECTIONS4 { 
                          local thiscolour : word `j' of `colours'  
                          local call `call' || rcap upper`D' lower`D' intersections4, lc(`thiscolour') 
                          local ++j 
                      }
                      
                      twoway `call' || scatter intersections4_hba1c_40 intersections4, mc(`colours') legend(off) scheme(s1color) xla("")
                      Note that although the error bars do change colour as desired, this sets all the markers to black for some reason, unlike in the example given above.

                      Comment


                      • #12
                        Ah yes. That's soluble. Your case is similar except for cycling round a set of 5 colours.

                        Code:
                        clear 
                        set obs 21 
                        gen date = _n 
                        gen mean = _n 
                        gen std = 1 
                        
                        separate mean, by(date) veryshortlabel
                        local means `r(varlist)'
                        
                        gen upper = mean + std 
                        gen lower = mean - std 
                        separate upper, by(date) veryshortlabel
                        separate lower, by(date) veryshortlabel 
                        
                        local colours black blue orange magenta red pink teal 
                        
                        levelsof date, local(DATES)
                        
                        local call 
                        local j = 1 
                        foreach D of local DATES { 
                            if `j' == 8 local j = 1 
                            local thiscolour : word `j' of `colours'  
                            local call `call' || rcap upper`D' lower`D' date, lc(`thiscolour')  || scatter mean`D' date, mc(`thiscolour')
                            local ++j 
                        }
                        
                        twoway `call'  legend(off) scheme(s1color) xla(`DATES')

                        Comment


                        • #13
                          Hi Nick just to report back and say this worked a treat. Again, thanks very much - it's really satisfying to see the graph I was imagining actually realised.
                          Best,
                          Dan

                          Comment


                          • #14
                            Thanks for the closure. Some of the small tricks here are more applicable. separate has been flagged elsewhere, as at https://www.stata-journal.com/sjpdf....iclenum=gr0023

                            Comment


                            • #15
                              Yes that's handy thanks. This has also been my first exposure to the world of macros. Evidently, they open up a lot of possibilities.

                              Comment

                              Working...
                              X