Announcement

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

  • Superimposing a vertical line on histogram

    Hello everyone,

    I’ve been trying to figure this out for hours, but I couldn’t find an answer on this forum or elsewhere online.

    I need to plot a vertical line on a histogram. However, I’m running into two issues with the xline option:
    1. If the line value falls within the histogram range, the vertical line is drawn behind the histogram, so it doesn’t show clearly.
    2. If the line value lies outside the automatically chosen x-range, the line doesn’t appear at all.
    Here’s a minimal example that demonstrates the problem:
    Code:
      sysuse auto, clear
    twoway (histogram price, frac), xline(5500 20000)
    At x = 5500, the red line is hidden behind the histogram, and at x = 20000, the line doesn’t appear because it’s outside the default range.

    Any help would be greatly appreciated!
    Attached Files
    Last edited by Demetrio Guzzardi; 20 Aug 2025, 03:20.

  • #2
    Use -twoway- with fcolor and xscale options:
    Code:
    syuse auto
    twoway (histogram price, fraction fcolor(%50)), xscale(range(5000 20000)) xline(5500 20000)
    Last edited by Dirk Enzmann; 20 Aug 2025, 03:44. Reason: Corrected first value of xline

    Comment


    • #3
      In addition to Dirk Enzmann's excellent answer, please note a miniature review

      Code:
      SJ-24-3 gr0097  . . . . . . . . .  Stata tip 157: Adding extra lines to graphs
              . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  N. J. Cox
              Q3/24   SJ 24(3):546--550                                (no commands)
              provides a miniature review of how you can add extra lines
              to graphs
      https://journals.sagepub.com/doi/pdf...6867X241276116

      This is more elaborate than might be wished, but it shows some technique.
      Code:
       
       sysuse auto, clear twoway (histogram price, frac), xline(5500 20000)  twoway histogram price, frac /// || scatteri 0 5500 0.5 5500, recast(line) pstyle(p2) /// || scatteri 0  20000 0.5 20000, recast(line) pstyle(p2) /// legend(off) xtitle("`: var label price' (USD)") ytitle(Fraction)

      Comment


      • #4
        Thank you both!

        The issue of the overlay seem to be solved with Nick option which is a bit caothic but it works. The workaround of making the bar somewhat transparent is not quite what I need.
        However both solutions imply that I manually set the ranges of the y axis. Unfortuntely I have dozens of graphs to make witithin a loop so I would prefer an option with an automatic adjustment of the range if it exist (?)

        Comment


        • #5
          You can run sum myvar, meanonly and subquently use the r-returns r(min) and r(max) to automatically use the values needed in your twoway command, see help stored results (and the respective manual entry that is more detailed).

          Comment


          • #6
            Don't you manually insert the xline positions? If so, Stata’s principle is that you can expand the range of the axis but cannot truncate it. Therefore, specifying -xscale(range(5500 20000))- should work to expand the range, and it will be ignored if the values already lie within it.

            Comment


            • #7
              #3 The code would look better laid out like this:

              Code:
               
               sysuse auto, clear   twoway (histogram price, frac), xline(5500 20000)    twoway histogram price, frac ///  || scatteri 0 5500 0.5 5500, recast(line) pstyle(p2) ///  || scatteri 0  20000 0.5 20000, recast(line) pstyle(p2) ///  legend(off) xtitle("`: var label price' (USD)") ytitle(Fraction)
              Sorry about the mess earlier.

              Comment


              • #8
                Arghhh! Same problem.

                Comment


                • #9
                  Thank you for the help. I think there was a misunderstanding, though. I would like to avoid specifying the y-axis range for the scatteri command, not the x-axis.

                  For the x-axis with scatteri there are no issues. The xrange option suggested by Andrew works well with xline, but the problem remains that the line extends below the histogram, while I want the line to be shown on top of the histogram.

                  In the end, I solved this with a workaround suggested to me here some time ago, which makes use of the undocumented twoway__histogram_gen.

                  I use twoway__histogram_gen to create the values of the horizontal bars in the histogram, and I then use the maximum of those values to set the y-axis in scatteri.
                  It’s not the cleanest solution, but it gets the job done.

                  Thank you everyone for the suggestions!


                  Code:
                         sysuse auto, clear 
                  
                         twoway__histogram_gen price, frac gen(h x, replace)
                         su h 
                         local max_h=round(`r(max)', 0.1)
                         twoway (histogram price, frac) (scatteri 0 5500 `max_h' 5500, recast(line) pstyle(p2)) (scatteri 0  20000 `max_h' 20000, recast(line) pstyle(p2))

                  Comment


                  • #10
                    Originally posted by Demetrio Guzzardi View Post
                    For the x-axis with scatteri there are no issues. The xrange option suggested by Andrew works well with xline, but the problem remains that the line extends below the histogram
                    You can always get rid of the bottom margin (see highlighted).

                    Code:
                    sysuse auto, clear   
                    twoway histogram price, frac ///
                    || scatteri 0 5500 0.5 5500, recast(line) pstyle(p2) ///  
                    || scatteri 0  20000 0.5 20000, recast(line) pstyle(p2) ///  
                    legend(off) xtitle("`: var label price' (USD)") ///
                    ytitle(Fraction) xsc(r(5500 20000)) plotregion(margin(b=0))

                    Click image for larger version

Name:	Graph.png
Views:	1
Size:	21.0 KB
ID:	1781221

                    Comment


                    • #11
                      Ignore #10. My interpretation of "below" was "below the value 0 on the y-axis" rather than underneath the graph. My point in #6 was that you need to specify the x-line positions manually anyway, so I didn’t see how Nick’s code introduced any additional overhead beyond that.

                      Comment

                      Working...
                      X