Announcement

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

  • Adding Percent Sign to Labels in Bar Graph

    I'd like to display the labels for the bar graph below as percents (with a "%" sign after them), but don't know how to do this beyond manually adding them using blabel().

    I am looking for a solution that's automated. Please correct me if this is wrong, but I don't think that there is a way to format variables to include percents that would then show up in a graph (as there is for commas).

    sysuse auto, clear
    generate p_over_5k = 0
    replace p_over_5k = 1 if price > 5000
    generate mileage = "Low" if mpg < 20
    replace mileage = "High" if mpg >= 20
    generate ones = 1
    collapse (sum) ones p_over_5k, by(foreign mileage)
    generate pr_over_5k = round(p_over_5k/ones, 0.01)*100
    graph bar (asis) pr_over_5k, over(foreign) over(mileage) asyvars blabel(bar) ytitle("Percent of Cars Over $5,000")

    Thank you for any assistance you can provide,
    Erika

  • #2
    Dear Erika, something like this? Thanks for providing a starter. Sergiy.

    Code:
    sysuse auto, clear
    generate p_over_5k = 0
    replace p_over_5k = 1 if price > 5000
    generate mileage = "Low" if mpg < 20
    replace mileage = "High" if mpg >= 20
    generate ones = 1
    collapse (sum) ones p_over_5k, by(foreign mileage)
    generate pr_over_5k = round(p_over_5k/ones, 0.01)*100
    graph bar (asis) pr_over_5k, over(foreign) over(mileage) asyvars blabel(bar) ytitle("Percent of Cars Over $5,000")
    
    local nb=`.Graph.plotregion1.barlabels.arrnels'
    forval i=1/`nb' {
      di "`.Graph.plotregion1.barlabels[`i'].text[1]'"
      .Graph.plotregion1.barlabels[`i'].text[1]="`.Graph.plotregion1.barlabels[`i'].text[1]'%"
    }
    .Graph.drawgraph

    Comment


    • #3
      Thank you for this information and solution, Sergiy. Can you explain a bit more about how this loop works? It looks like it's calling specific elements of the graph, but I'm not familiar with the term "arrnels" (in the first line of the new code) or this method for modifying a graph.

      And can you confirm that there isn't a way to format a variable to include a percent sign (as there is with commas)?

      Thank you again,
      Erika

      Comment


      • #4
        Adding percent signs doesn't count as a Stata format. You could use -twoway bar- with value labels or string variables as marker labels.

        Comment


        • #5
          Originally posted by Erika Kociolek View Post
          Thank you for this information and solution, Sergiy. Can you explain a bit more about how this loop works? It looks like it's calling specific elements of the graph, but I'm not familiar with the term "arrnels" (in the first line of the new code) or this method for modifying a graph.

          And can you confirm that there isn't a way to format a variable to include a percent sign (as there is with commas)?

          Thank you again,
          Erika
          Erika,

          1) the loop works with the graph labels directly attaching the percent sign to every original label. Code like this requires knowledge of the internals of Stata graphics. This is advanced stuff and it is not documented. It just works.
          For arrnels on the other hand: see the class programming manual. In this case it is just a number of labels.
          You may do any transformations to the original labels (multiply/divide by 100, check for empty labels, attach $, % or something else, etc depending on the task).

          2) Yes, just as Nick has already confirmed, you can't create a format containing % in Stata.

          Best, Sergiy

          Comment


          • #6
            Dear Sergiy,

            How do I have to adjust your loop for it to work in a combined graph with two bar charts?

            Many thanks,
            Boris

            Comment


            • #7
              Boris, notice how Erika has started her question with a starter code. Doing this increases the chances of response greatly. Best, Sergiy Radyakin

              Code:
              clear all
              sysuse auto, clear
              generate p_over_5k = 0
              replace p_over_5k = 1 if price > 5000
              generate mileage = "Low" if mpg < 20
              replace mileage = "High" if mpg >= 20
              generate ones = 1
              collapse (sum) ones p_over_5k, by(foreign mileage)
              generate pr_over_5k = round(p_over_5k/ones, 0.01)*100
              graph bar (asis) pr_over_5k, over(foreign) over(mileage) asyvars blabel(bar) ytitle("Percent of Cars Over $5,000") name(G1)
              graph bar (asis) pr_over_5k, over(foreign) over(mileage) asyvars blabel(bar) ytitle("Percent of Cars Over $5,000") name(G2) bar(1,color(green)) bar(2,color(yellow)) 
              
              graph combine G1 G2
              
              local ng=`.Graph.graphs.arrnels'
              forval g=1/`ng' {
                  local nb=`.Graph.graphs[`g'].plotregion1.barlabels.arrnels'
                  forval i=1/`nb' {
                    di "`.Graph.graphs[`g'].plotregion1.barlabels[`i'].text[1]'"
                    .Graph.graphs[`g'].plotregion1.barlabels[`i'].text[1]="`.Graph.graphs[`g'].plotregion1.barlabels[`i'].text[1]'%"
                  }
              }
              .Graph.drawgraph
              Click image for larger version

Name:	combined.png
Views:	1
Size:	68.3 KB
ID:	1345385

              Comment


              • #8
                If you use twoway bar instead, you can knit your own bar label. This uses Sergiy's example, except that it doesn't show two versions of the same graph. No need for graph editor adjustments.


                Code:
                clear all
                set scheme s1color 
                sysuse auto, clear
                
                generate mileage = mpg >= 20 
                label def mileage 0 "Low" 1  "High"
                label val mileage mileage 
                
                egen pc_over_5k = mean(100 * (price > 5000)), by(foreign mileage) 
                gen tolabel = string(pc_over_5k, "%2.0f") + "%" 
                
                twoway bar pc_over_5k mileage, base(0) barw(0.5) bfcolor(green*0.2)  ///
                by(foreign, note("") legend(off)) ///
                || scatter pc_over_5k mileage, ms(none) ysc(r(0 105)) yla(0(20)100) ///
                mlabel(tolabel) mlabpos(12) mlabcolor(black) xla(0 1, tlcolor(none) valuelabel) ///
                ytitle(% of cars > USD 5000)
                Click image for larger version

Name:	barbar.png
Views:	1
Size:	34.8 KB
ID:	1345408

                Comment


                • #9
                  How could we use a similar code to the one Sergiy Radyakin shared to add percent symbols to the height labels of a histogram? Here is an example where I have height labels, but I would like to be able to add the percent symbol without doing it manually for each. Unfortunately, the code for the bar graph doesn't work with a histogram, and while I generally don't love histograms, there are times when they are useful.

                  Code:
                  sysuse auto, clear
                  hist mpg, percent addlabels addlabopts(mlabformat(%4.1fc))

                  Comment


                  • #10
                    Code:
                    sysuse auto, clear
                    twoway__histogram_gen mpg, frac gen(h x)
                    replace h = h*100
                    gen h_str = strofreal(h,"%3.1f") + "%" 
                    twoway bar h x, mlabel(h_str) barwidth(`=x[2]-x[1]') xlabel(10(10)40) ytitle("Percent") scheme(s1color) color(gs6) mlabcolor(black)
                    which produces

                    Click image for larger version

Name:	Screenshot 2022-10-25 at 9.59.24 AM.png
Views:	1
Size:	124.7 KB
ID:	1686636

                    Comment


                    • #11
                      #9 and #10 To spell it out, you don't need Graph Editor trickery because histogram belongs to the twoway family so adding marker labels directly is possible. In fact #10 is neater than #8 in how that was done.

                      Comment


                      • #12
                        Interesting thank you. I understand that you're manually creating the label here, but when I copy the exact syntax into my Stata window there are no labels that appear on the bar. Why not?

                        Code:
                        sysuse auto, clear
                        
                        twoway__histogram_gen mpg, frac gen(h x)
                            replace h = h*100
                            gen h_str = strofreal(h,"%3.1f") + "%"
                        
                        twoway bar h x, ///
                                mlabel(h_str) mlabcolor(black) ///
                                barwidth(`=x[2]-x[1]') ///
                                xlabel(10(10)40) ytitle("Percent") ///
                                scheme(s1color) color(gs6)
                        Produced the attached graphic. What am I missing here?
                        Attached Files
                        Last edited by Kenzie Reid; 27 Oct 2022, 15:21.

                        Comment


                        • #13
                          Came across this post and wanted to revive it as I have a kind of hackish solution to this issue that uses one of the -over()- layers to display string labels using -graph bar-.

                          The general idea is that the user will have to save the analysis results and do processing on them in the active dataset. This allows the user to make an -over()- variable with a label that is can be mostly ignored except for its application in -blabel(group)- that will display the processed labels.

                          A reproducible example with the graph it generates is posted below.

                          Hope this might help those looking to add string labels to their graph.


                          Code:
                          sysuse nlsw88, clear
                          gen b = .
                          generate str50 lab = ""
                          proportion married#collgrad, over(smsa)
                          mata: st_store(1::8, "b", st_matrix("e(b)")')
                          replace b = b*100
                          mata: st_sstore(1::8, "lab", st_matrixcolstripe("e(b)")[,2])
                          split lab, generate(sub_lab) parse("@")
                          split sub_lab1, generate(sub_sub_lab) parse("#")
                          generate smsa2 = real(substr(sub_lab2, 1, 1))
                          label values smsa2 smsalbl
                          label variable smsa2 "Lives in SMSA"
                          generate married2 = real(substr(sub_sub_lab1, 1, 1))
                          label values married2 marlbl
                          generate collgrad2 = real(substr(sub_sub_lab2, 1, 1))
                          label values collgrad2 gradlbl
                          generate vallab = string(round(b)) + "%"
                          graph bar b, over(married2) over(vallab, axis(off) gap(0)) over(collgrad2) blabel(group) by(smsa2) nofill asyvars ytitle("Percentage")
                          Attached Files
                          Last edited by Joseph Luchman; 20 Nov 2024, 13:02. Reason: Fixing graph
                          Joseph Nicholas Luchman, Ph.D., PStatĀ® (American Statistical Association)
                          ----
                          Research Fellow
                          Fors Marsh

                          ----
                          Version 18.0 MP

                          Comment

                          Working...
                          X