Announcement

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

  • How can I add transformed coefficient values as mlabels to coefplot?

    Dear all,

    I use coefplot to show salary differences. With the code below I can display the values of the respective coefficients directly at each bar.

    coefplot (c1, label(Total content: Unadjusted) pstyle(p1)) ///
    (c2, label(total salary: adjusted) pstyle(p2)) ///
    (c3, label(Base salary: Unadjusted) pstyle(p3)) ///
    (c4, label(Base salary: Adjusted) pstyle(p4)) ///
    , ci(95) vertical recast(bar) keep(male) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
    citop xlabel("") xtitle("") ylabel(-0.02(0.04)0.22, format(%4.2f) labsize(small)) ytitle("") ///
    title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6)) ///
    addplot(scatter @b @at, ms(i) mlabel(@b) mlabformat(%4.3f) mlabpos(2) mlabcolor(black)) ///
    aspectratio(2) ysize(2) xsize(1) scale(2) ///
    save("$workdir/graph.gph", replace)

    Now I want to convert the values to percentages and display them directly on the graph. For the transformation I use (exp( b )-1)*100.

    How is it possible to integrate the transformed values as mlabels in coefplot?

    I would be very grateful for an answer or any idea.

    Best regards
    Isea Cieply

  • #2
    coefplot is from SSC (FAQ Advice #12). Provide a reproducible example as recommended in FAQ Advice #12. You can use one of Stata's datasets.

    Comment


    • #3
      Dear Andrew,

      thank you for your advice. Here you find an example code that regresses the impact of being unmarried on wages.
      How can I make Stata display the coefficients in percentages?

      use "https://www.stata-press.com/data/r17/nlsw88.dta", clear

      reg wage never_married
      est store c1

      reg wage never_married c.age##c.tenure
      est store c2

      reg wage never_married c.tenure
      est store c3

      reg wage never_married c.grade
      est store c4

      coefplot (c1, label(Wage 1) pstyle(p1)) ///
      (c2, label(Wage 2) pstyle(p2)) ///
      (c3, label(Wage 3) pstyle(p3)) ///
      (c4, label(Wage 4) pstyle(p4)) ///
      , ci(95) vertical recast(bar) keep(never_married) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
      citop xlabel("") xtitle("") ylabel(, format(%4.2f) labsize(small)) ytitle("") ///
      title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6)) ///
      addplot(scatter @b @at, ms(i) mlabel(@b) mlabformat(%4.3f) mlabpos(2) mlabcolor(black)) ///
      aspectratio(2) ysize(2) xsize(1) scale(2)
      graph save "$workdir/graph.gph", replace

      graph export "$workdir/graph.pdf", replace

      Attached Files

      Comment


      • #4
        Thanks. Here is one approach using estadd from estpost (SSC).

        Code:
        use "https://www.stata-press.com/data/r17/nlsw88.dta", clear
        
        reg wage never_married
        est store c1
        mat pct= e(b)
        forval i=1/`=colsof(pct)'{
            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
        }
        estadd mat pct= pct: c1
        
        
        
        reg wage never_married c.age##c.tenure
        est store c2
        mat pct= e(b)
        forval i=1/`=colsof(pct)'{
            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
        }
        estadd mat pct= pct: c2
        
        
        reg wage never_married c.tenure
        est store c3
        mat pct= e(b)
        forval i=1/`=colsof(pct)'{
            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
        }
        estadd mat pct= pct: c3
        
        reg wage never_married c.grade
        est store c4
        mat pct= e(b)
        forval i=1/`=colsof(pct)'{
            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
        }
        estadd mat pct= pct: c4
        
        set scheme s1color
        
        coefplot (c1, label(Wage 1) pstyle(p1)) ///
        (c2, label(Wage 2) pstyle(p2)) ///
        (c3, label(Wage 3) pstyle(p3)) ///
        (c4, label(Wage 4) pstyle(p4)) ///
        , ci(95) vertical recast(bar) keep(never_married) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
        citop xlabel("") xtitle("") ylabel(, format(%4.2f) labsize(small)) ytitle("") ///
        title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6)) ///
        addplot(scatter @b @at, ms(i) mlabel(@b) mlabformat(%4.3f) mlabpos(2) mlabcolor(black)) ///
        aspectratio(2) ysize(2) xsize(1) scale(2) saving(gr1, replace) title(Original)
        
        coefplot (c1, label(Wage 1) pstyle(p1)) ///
        (c2, label(Wage 2) pstyle(p2)) ///
        (c3, label(Wage 3) pstyle(p3)) ///
        (c4, label(Wage 4) pstyle(p4)) ///
        , aux(pct) ci(95) vertical recast(bar) keep(never_married) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
        citop xlabel("") xtitle("") ylabel(, format(%4.2f) labsize(small)) ytitle("") ///
        title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6)) ///
        addplot(scatter @b @at, ms(i) mlabel(@aux1) mlabformat(%4.3f) mlabpos(2) mlabcolor(black)) ///
        aspectratio(2) ysize(2) xsize(1) scale(2) saving(gr2, replace) title(Wanted)
        
        gr combine gr1.gph gr2.gph
        I think it should also be possible just to use the -transform()- option. Will post this once I get more time.

        Res.:

        Click image for larger version

Name:	Graph.png
Views:	1
Size:	40.9 KB
ID:	1730032

        Comment


        • #5
          Wow, that's amazing. Thank you very much for your help, that is exactly what I needed.

          Comment


          • #6
            Do you by chance also know, how I could add the percentage sign here, such that the values are displayed like 128.950%?

            Comment


            • #7
              There is no need for -addplot()- if your sole intention is to add marker labels. This just constrains you to twoway options which are not flexible in terms of manipulating the labels. Just use coefplot to add the labels. In this way, the transformation of coefficients is also straightforward, which I am yet to illustrate.

              Code:
              use "https://www.stata-press.com/data/r17/nlsw88.dta", clear
              
              reg wage never_married
              est store c1
              mat pct= e(b)
              forval i=1/`=colsof(pct)'{
                  mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
              }
              estadd mat pct= pct: c1
              
              
              
              reg wage never_married c.age##c.tenure
              est store c2
              mat pct= e(b)
              forval i=1/`=colsof(pct)'{
                  mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
              }
              estadd mat pct= pct: c2
              
              
              reg wage never_married c.tenure
              est store c3
              mat pct= e(b)
              forval i=1/`=colsof(pct)'{
                  mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
              }
              estadd mat pct= pct: c3
              
              reg wage never_married c.grade
              est store c4
              mat pct= e(b)
              forval i=1/`=colsof(pct)'{
                  mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
              }
              estadd mat pct= pct: c4
              
              set scheme s1color
              
              coefplot (c1, label(Wage 1) pstyle(p1)) ///
              (c2, label(Wage 2) pstyle(p2)) ///
              (c3, label(Wage 3) pstyle(p3)) ///
              (c4, label(Wage 4) pstyle(p4)) ///
              , aux(pct) ci(95) vertical recast(bar) keep(never_married) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
              mlabel(string(@aux1, "%4.3f") + "%") mlabc(black) mlabgap(.5cm) mlabpos(1) ///
              citop xlabel("") xtitle("") ylabel(, format(%4.2f) labsize(small)) ytitle("") ///
              title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6))
              Click image for larger version

Name:	Graph.png
Views:	1
Size:	19.7 KB
ID:	1730106

              Comment


              • #8
                So it is this simple if you use coefplot to add the labels.

                Code:
                use "https://www.stata-press.com/data/r17/nlsw88.dta", clear
                
                reg wage never_married
                est store c1
                
                reg wage never_married c.age##c.tenure
                est store c2
                
                reg wage never_married c.tenure
                est store c3
                
                reg wage never_married c.grade
                est store c4
                
                
                set scheme s1color
                
                coefplot (c1, label(Wage 1) pstyle(p1)) ///
                (c2, label(Wage 2) pstyle(p2)) ///
                (c3, label(Wage 3) pstyle(p3)) ///
                (c4, label(Wage 4) pstyle(p4)) ///
                , ci(95) vertical recast(bar) keep(never_married) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
                mlabel(string((exp(@b)-1)*100, "%4.3f") + "%") mlabc(black) mlabgap(.5cm) mlabpos(1) ///
                citop xlabel("") xtitle("") ylabel(, format(%4.2f) labsize(small)) ytitle("") ///
                title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6))

                Comment


                • #9
                  Is is possible to perform this with Stata 16? Because, when I run your Code, no labels are displayed.
                  Attached Files

                  Comment


                  • #10
                    Update coefplot and try again.

                    Code:
                    ssc install coefplot, replace

                    Comment


                    • #11
                      still does not seem to work with Stata 16. Can you get the same result with -addplot()-?

                      Comment


                      • #12
                        It's just a hassle. You'll need to do some extra tweaking with values that have only one digit before the decimal point (although that's not the case here).

                        Code:
                        use "https://www.stata-press.com/data/r17/nlsw88.dta", clear
                        
                        reg wage never_married
                        est store c1
                        mat pct= e(b)
                        forval i=1/`=colsof(pct)'{
                            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                        }
                        estadd mat pct= pct: c1
                        
                        
                        
                        reg wage never_married c.age##c.tenure
                        est store c2
                        mat pct= e(b)
                        forval i=1/`=colsof(pct)'{
                            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                        }
                        estadd mat pct= pct: c2
                        
                        
                        reg wage never_married c.tenure
                        est store c3
                        mat pct= e(b)
                        forval i=1/`=colsof(pct)'{
                            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                        }
                        estadd mat pct= pct: c3
                        
                        reg wage never_married c.grade
                        est store c4
                        mat pct= e(b)
                        forval i=1/`=colsof(pct)'{
                            mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                        }
                        estadd mat pct= pct: c4
                        
                        set scheme s1color
                        gen newvar1= "`=uchar(28)'             %"
                        gen newvar2= "`=uchar(28)'           %"
                        
                        coefplot (c1, label(Wage 1) pstyle(p1)) ///
                        (c2, label(Wage 2) pstyle(p2)) ///
                        (c3, label(Wage 3) pstyle(p3)) ///
                        (c4, label(Wage 4) pstyle(p4)) ///
                        , aux(pct) ci(95) vertical recast(bar) keep(never_married) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
                        citop xlabel("") xtitle("") ylabel(, format(%4.2f) labsize(small)) ytitle("") ///
                        title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6)) ///
                        addplot((scatter @b @at, ms(i) mlabel(@aux1) mlabformat(%4.3f) mlabpos(2) mlabcolor(black)) ///
                        (scatter @b @at if int(@aux)>=100, ms(none) mlabel(newvar1) mlabpos(2)  mlabcolor(black)) ///
                        (scatter @b @at if int(@aux)<100, ms(none) mlabel(newvar2) mlabpos(2) mlabcolor(black))) ///
                        saving(gr2, replace) title(Wanted)
                        Click image for larger version

Name:	Graph.png
Views:	1
Size:	17.3 KB
ID:	1730169

                        Comment


                        • #13
                          Thank you very much! I have another question: How can I transform the vertical axis into % as well? If I use something like ylabel(-0.5 "-50%" 0.00 "0%" 0.5 "50%" 1.0 "100%" 1.5 "150%", format(%4.2f), the y-axis shows the coefficient values with % signs, but not the transformed values that match my percentage values of the coefficients in the graph. How can I adjust both values to percentages? Any ideas? Thank you very much!
                          Last edited by Isea Cieply; 02 Nov 2023, 03:17.

                          Comment


                          • #14
                            Apply the same transformation that you did to the coefficients.

                            Code:
                            use "https://www.stata-press.com/data/r17/nlsw88.dta", clear
                            
                            reg wage never_married
                            est store c1
                            mat pct= e(b)
                            forval i=1/`=colsof(pct)'{
                                mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                            }
                            estadd mat pct= pct: c1
                            
                            
                            
                            reg wage never_married c.age##c.tenure
                            est store c2
                            mat pct= e(b)
                            forval i=1/`=colsof(pct)'{
                                mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                            }
                            estadd mat pct= pct: c2
                            
                            
                            reg wage never_married c.tenure
                            est store c3
                            mat pct= e(b)
                            forval i=1/`=colsof(pct)'{
                                mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                            }
                            estadd mat pct= pct: c3
                            
                            reg wage never_married c.grade
                            est store c4
                            mat pct= e(b)
                            forval i=1/`=colsof(pct)'{
                                mat pct[1, `i']= (exp(pct[1, `i'])-1)*100
                            }
                            estadd mat pct= pct: c4
                            
                            set scheme s1color
                            gen newvar1= "`=uchar(28)'             %"
                            gen newvar2= "`=uchar(28)'           %"
                            
                            coefplot (c1, label(Wage 1) pstyle(p1)) ///
                            (c2, label(Wage 2) pstyle(p2)) ///
                            (c3, label(Wage 3) pstyle(p3)) ///
                            (c4, label(Wage 4) pstyle(p4)) ///
                            , aux(pct) ci(95) vertical recast(bar) keep(never_married) barwidth(0.15) fcolor(*.5) ciopts(recast(rcap)) ///
                            citop xlabel("") xtitle("") ylabel(, format(%4.2f) labsize(small)) ytitle("") ///
                            title("") graphregion(color(white)) yline(0, lcolor(black) lpattern(dashed)) legend(cols(1) pos(6)) ///
                            addplot((scatter @b @at, ms(i) mlabel(@aux1) mlabformat(%4.3f) mlabpos(2) mlabcolor(black)) ///
                            (scatter @b @at if int(@aux)>=100, ms(none) mlabel(newvar1) mlabpos(2)  mlabcolor(black)) ///
                            (scatter @b @at if int(@aux)<100, ms(none) mlabel(newvar2) mlabpos(2) mlabcolor(black))) ///
                            saving(gr2, replace) title(Wanted) ///
                            ylab(-0.5 "`:di %3.2f `=(exp(-0.5)-1)*100''" 0 "`:di %3.0f `=(exp(0)-1)*100''" 0.5 "`:di %3.2f `=(exp(0.5)-1)*100''" 1 "`:di %3.2f `=(exp(1)-1)*100''" 1.5 "`:di %3.2f `=(exp(1.5)-1)*100''")
                            Click image for larger version

Name:	Graph.png
Views:	1
Size:	27.1 KB
ID:	1732457

                            Comment


                            • #15
                              Thank you very much! This is a correct solution of course, but what I really want is to have values like 0, 50, 100% on the y-axis and not these exact values. Is there a good way to do that? Or would another tool be easier here, like twoway graph?

                              Comment

                              Working...
                              X