Announcement

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

  • Marginsplot: Changing markers by categorical value along x-axis

    I am summarizing percentage estimates across cities graphically, using margins and marginsplot. However, for particular cities I wish to make the marker a different symbol. (And I want the legend to include both the primary symbol and that special symbol.) While I can change markers by margin using plot1opt, plot2opt, etc., I don't see how to change marker according to categorical value --- that is, according to the categories listed along the x-axis.

    Here is reproducible example of my problem, below. The first graph works fine, but imagine that I wanted to change the SECOND marker to a square rather than a circle. I can't figure out how to do it; neither of the two attempts at the bottom are successful.

    I'm open to code that gets at the same figure without margins(plot). I tried unsuccessful hacks with both combomarginsplot and coefplot.


    Code:
    sysuse auto.dta, clear
    gen heavy=weight>3500
    gen cat = substr(make, 1, strpos(make, " ") - 1) 
    bysort cat: gen x=_n
    bysort cat: egen y=max(x)
    drop if x==y
    encode(cat), gen(emake)
    drop if emake==.
    
    reg heavy i.emake
    margins emake
    
    * this works fine, but let's say I want the SECOND market to be a square
    marginsplot, recast(scatter) ///
        plotopts(msymbol(O))
    
    * this doesn't work; it's for various margins not various values
    marginsplot, recast(scatter) ///
        plotopts(msymbol(O)) plot2opts(msymbol(S))
        
    * this felt like it might work, but it doesn't
    marginsplot, recast(scatter) ///
        plotopts(msymbol(O S O O O O O O O O O O O O O O O O O O))
    ​​​

  • #2
    Leah, your question is exactly the same as the one in the linked thread from yesterday. You have exactly one plot, so you cannot change the individual markers. I suggest a solution using coefplot from SSC. Let me know if you face problems implementing it.

    https://www.statalist.org/forums/for...insplot-to-bar

    Comment


    • #3
      Thanks! This does indeed look like a good work-around. However, when I run this full code, exactly as you posted it, I get no output but this error, after running the last coefplot command: "too many names specified"

      Any idea why? I literally upgraded to Stata 17 on Tuesday, if that's relevant. I'm also unable to run the example given in the help file for erepost, so I'm guessing the problem is with that command (which I've never used before, and don't really understand even after reading that help file).
      Last edited by Leah Bevis; 09 Sep 2021, 10:19.

      Comment


      • #4
        What happens if you run the code specifying version 16 at the top? I do not have version 17 to test, but it runs fine on my version 16.

        Code:
        version 16.1
        estimates clear
        ssc install erepost, replace
        
        cap prog drop repb
        program repb, eclass
        erepost b=b, rename
        end
        
        sysuse auto, clear
        reg price c.mpg##foreign 
        eststo all
        local i 1
        forval mpg= 20(10)40{
            forval foreign=0/1{
                est restore all
                margins, at(mpg=(`mpg') foreign=(`foreign')) vsquish post
                mat b=e(b)
                mat colname b= _at`i'
                repb
                eststo m`i'
                local ++i
             }
        }
        set scheme s1color
        coefplot m*,  vert ytitle("Linear Prediction") recast(bar) nokey

        Comment


        • #5
          Oddly, the same error occurs after I run that precise code above. ("too many names specified.") In fact, I reran the same code on 14.2, which I have on my old laptop, and I get the same error! So, seems to be a problem with erepost and not the Stata version. (Coefplot is working fine.)

          Is there some user-installed command that underlies erepost, that I'm missing? When I run the sample code under help for erepost:

          Code:
          sysuse auto, clear
          generate foreign_mpg = foreign*mpg
          generate foreign_weight = foreign*weight
          quietly regress price foreign_mpg foreign_weight foreign mpg weight
          matrix b = e(b)
          matrix coleq b = foreign foreign foreign main main main
          matrix colname b = mpg weight _cons mpg weight _cons
          erepost b=b, rename
          esttab , unstack order(main: foreign:)
          I get this error after the last line: "equation main not found". Also, I don't know if I'm supposed to be able to see matrix b after the erepost line, but if so, I can't. (I.e., mat lis b shows b prior to the erepost line, but not after.)

          Or is there, perhaps, a new version of erepost that you are using and I am not? I may have installed from the wrong source? My help links it to this site: https://ideas.repec.org/c/boc/bocode/s456850.html

          Comment


          • #6
            Your code runs perfectly for me. It may be that you do not have the latest version of estout.

            Adding

            Code:
            sysuse auto, clear
            generate foreign_mpg = foreign*mpg
            generate foreign_weight = foreign*weight
            quietly regress price foreign_mpg foreign_weight foreign mpg weight
            mat l e(b)
            matrix b = e(b)
            matrix coleq b = foreign foreign foreign main main main
            matrix colname b = mpg weight _cons mpg weight _cons
            erepost b=b, rename
            mat l e(b)
            esttab , unstack order(main: foreign:)
            which erepost
            which estout
            I get

            Code:
            . sysuse auto, clear
            (1978 Automobile Data)
            
            .
            . generate foreign_mpg = foreign*mpg
            
            .
            . generate foreign_weight = foreign*weight
            
            .
            . quietly regress price foreign_mpg foreign_weight foreign mpg weight
            
            .
            . mat l e(b)
            
            e(b)[1,6]
                 foreign_mpg  foreign_we~t       foreign           mpg        weight         _cons
            y1    -257.46832     .74080536     8219.6031     237.69095     4.4150368    -13285.444
            
            .
            . matrix b = e(b)
            
            .
            . matrix coleq b = foreign foreign foreign main main main
            
            .
            . matrix colname b = mpg weight _cons mpg weight _cons
            
            .
            . erepost b=b, rename
            
            .
            . mat l e(b)
            
            e(b)[1,6]
                   foreign:    foreign:    foreign:       main:       main:       main:
                       mpg      weight       _cons         mpg      weight       _cons
            y1  -257.46832   .74080536   8219.6031   237.69095   4.4150368  -13285.444
            
            .
            . esttab , unstack order(main: foreign:)
            
            --------------------------------------------
                                  (1)                  
                                price                  
                                 main         foreign  
            --------------------------------------------
            mpg                 237.7          -257.5  
                               (1.90)         (-1.66)  
            
            weight              4.415***        0.741  
                               (5.18)          (0.45)  
            
            _cons            -13285.4*         8219.6  
                              (-2.58)          (1.13)  
            --------------------------------------------
            N                      74                  
            --------------------------------------------
            t statistics in parentheses
            * p<0.05, ** p<0.01, *** p<0.001
            
            .
            . which erepost
            
            *! version 1.0.2, Ben Jann, 15jun2015
            
            . which estout
            
            *! version 3.24  30apr2021  Ben Jann
            Last edited by Andrew Musau; 09 Sep 2021, 12:58.

            Comment


            • #7
              Yes -- my erepost is also 1.0.2, but my estout version was 3.17. I upgraded it to 3.24 like yours. Great. However, now something VERY odd is happening, and I can tell that it's stemming from eststo but I don't know why.

              (1) If I have just restarted Stata, OR if I begin first with eststo clear, I can run the following code with success:
              Code:
              sysuse auto, clear
              generate foreign_mpg = foreign*mpg
              generate foreign_weight = foreign*weight
              quietly regress price foreign_mpg foreign_weight foreign mpg weight
              matrix b = e(b)
              matrix coleq b = foreign foreign foreign main main main
              matrix colname b = mpg weight _cons mpg weight _cons
              erepost b=b, rename
              esttab , unstack order(main: foreign:)
              (2) However, if I first run this code here:
              Code:
              sysuse auto, clear
              reg price c.mpg##foreign
              eststo all
              And then run the code above under (1) without first running eststo clear, I get the same error as before after the esttab line ("equation main not found"). Also the code that ends with coefplot m* still doesn't run.

              Running just the regression reg price c.mpg##foreign doesn't break the code under (1), it's the eststo all that does it.

              which eststo tells me that I have: version 1.1.0 05nov2008 Ben Jann, which seems old compared to my 2021 version of estout. So I guess I need a new version of eststo? But (a) weird because I thought it came with estout, and (b) if not, I can't seem to find a way to re-install it. No matter what I try it's the same version 1.1.0. Ideas?
              Last edited by Leah Bevis; 09 Sep 2021, 14:46.

              Comment


              • #8
                Your eststo is up to date, and yes - it does come compiled with your estout. There is no mystery here. If you have results stored by eststo, any call to esttab or estout will prioritize those estimates (over non-stored estimates in memory). Therefore, either store the estimates using eststo or use a dot to output the active estimates.

                Code:
                sysuse auto, clear
                reg price c.mpg##foreign
                eststo all
                
                sysuse auto, clear
                generate foreign_mpg = foreign*mpg
                generate foreign_weight = foreign*weight
                quietly regress price foreign_mpg foreign_weight foreign mpg weight
                matrix b = e(b)
                matrix coleq b = foreign foreign foreign main main main
                matrix colname b = mpg weight _cons mpg weight _cons
                erepost b=b, rename
                esttab ., unstack order(main: foreign:)

                Comment


                • #9
                  Ok, that does work, though I'm not sure I follow why. But the more important point is, the original code that you posted yesterday / you pointed me to today still does not work. I was assuming it had something to do with eststo, but maybe not. In any case, it is still the case (after all the updates and restarts) that if I run this code:

                  Code:
                  cap prog drop repb
                  program repb, eclass
                  erepost b=b, rename
                  end
                  
                  sysuse auto, clear
                  reg price c.mpg##foreign 
                  eststo all
                  local i 1
                  forval mpg= 20(10)40{
                      forval foreign=0/1{
                          est restore all
                          margins, at(mpg=(`mpg') foreign=(`foreign')) vsquish post
                          mat b=e(b)
                          mat colname b= _at`i'
                          repb
                          eststo m`i'
                          local ++i
                       }
                  }
                  set scheme s1color
                  coefplot m*,  vert ytitle("Linear Prediction") recast(bar) nokey
                  I get no graph and the error: too many names specified

                  Comment


                  • #10
                    Additionally, I assume it is possible to color/marker the coefplots individually by number, rather than by scheme? Seems likely, but if not, perhaps I should have asked that first -- that would be a primary difference between my goal and your example.

                    Comment


                    • #11
                      I couldn't tell you why it doesn't run on your side. Works perfectly for me. And ditto to #2, the suggestion allows individual differentiation, e.g., third CI and marker below (highlighted). If you have access to your old Stata 16, try it.

                      Code:
                      cap prog drop repb
                      program repb, eclass
                      erepost b=b, rename
                      end
                      
                      sysuse auto, clear
                      reg price c.mpg##foreign 
                      eststo all
                      local i 1
                      forval mpg= 20(10)40{
                          forval foreign=0/1{
                              est restore all
                              margins, at(mpg=(`mpg') foreign=(`foreign')) vsquish post
                              mat b=e(b)
                              mat colname b= _at`i'
                              repb
                              eststo m`i'
                              local ++i
                           }
                      }
                      set scheme s1color
                      coefplot m*,  vert ytitle("Linear Prediction") recast(scatter) mcolor(blue) ciopts(color(blue)) p3(mcolor(red) ciopts(color(red))) nokey
                      Click image for larger version

Name:	Graph.png
Views:	1
Size:	17.1 KB
ID:	1626954

                      Comment


                      • #12
                        Wow. Ok I finally got this to work by upgrading to the newest version of coefplot. I think the whole thing was confusing because there are 3 different user-written commands embedded -- I knew one of them wasn't working (since I'd tried the same code on 2 laptops, and on both Stata 14 and Stata 17), but I was pretty sure it was one of the other two, not coefplot, since I have used coefplot successfully in other contexts. But I guess you are using a newer capability within it... Anyway, I suppose this is a lesson about always making sure user-written commands are in sync version-wise, when trying to copy somebody's code. Thank you SO MUCH for your help! This is brilliant, and I will definitely be using it.

                        Comment


                        • #13
                          For anyone looking for similar code in the future, I adapted Andrew's code a bit; it was faster to simply get means by data subset than to use regression + margins to get those means. (Previously I wasn't sure how to use coefplot to record means rather than regression output; turns out it works exactly the same.) The code ended up looking like this below, and the figure created is attached.

                          Code:
                          local CTY `"Seattle Hartford Tucson "New Orleans" Lincoln Columbus Cincinatti Bloomington Chandler Baltimore Sacramento"'
                          
                          eststo clear
                          local i 1
                          forval c = 1/11 {
                                  preserve
                                  keep if ecity==`c'
                                      qui mean BHRT1 if ecity==`c' 
                                      mat b=e(b)
                                      local a : word `i' of `CTY'
                                      mat colname b= "`a'"
                                      erepost b=b, rename
                                      eststo m`i'
                                  restore
                                  local ++i
                          }
                          coefplot m*,  vert ytitle("Linear Prediction") recast(scatter) mcolor(blue) ///
                              ciopts(color(blue)) p4(msymbol(S)) p5(msymbol(S)) ///
                              xlabel(, angle(45)) ytitle("Percent of Dispatches") ///
                              legend(order(2 "Calls for service and officer-initiated" ///
                                  8 "Calls for service and officer-initiated: subset of") rows(4)) ///
                              xtitle("High resolution/quality       <--       Data Quality       -->       Low resolution/quality")
                          Attached Files

                          Comment


                          • #14
                            Thanks for this, Leah! I had to wrap the erepost command within program in my code because I sometimes get an error "non e-class program may not set e()".

                            Comment

                            Working...
                            X