Announcement

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

  • graph bar with bar label from other variable

    Hi, im struggling to create graph that shows two variables side by side, over third one, but with additional label that would show additional information (like name of a country), for example like below with additional "make" variable above each group of the bar, like "Toyota etc". In my case there is only one make by weight values. Also is there a way to remove "mean of" in legend of the graph?

    Code:
    sysuse auto.dta, clear
    
    sort foreign weight
    graph bar mpg trunk if foreign==1, over(weight, lab(angle(45)))
    I could make like this in twoway but i do not like the sparsity and overlapping since weight there is not a category but just a value...

    Code:
    cap drop weight_
    gen weight_ = weight - 10
    
    twoway   bar mpg weight_ if foreign==1 , barw(10) legend(pos(6))  || bar trunk weight if foreign==1, barw(10) base(0)  || scatter mpg weight if foreign==1, mla(make) mlabpos(12) mlabcolor(black) ms(none)

  • #2
    (asis) overwrites the default that graph bar is inclined to calculate means. See its help for more detail.

    Otherwise, see https://www.statalist.org/forums/for...ailable-on-ssc for a command that seems intended for more or less your purpose.

    Comment


    • #3
      Thank you, i guess i will have to use multidot command ...

      Comment


      • #4
        You don't have to accept what isn't right for you. But while agreeing that the second graph in #1 is a mess, I can't follow quite what you want.

        You've given us a code example we can run (excellent, and thanks) but it's implausible as a graph.

        Comment


        • #5
          Using -multidot- is certainly a good choice. If you like bar plot, and want to add "make" label on the plot, and in the same time aviod sparsity (if not include overlapping), I think you can try to resort to Nick Cox's -labmask- command. Well, the code below still has some bugs, especially the max value of variable weight in the x-axis, however, I think it can be taken as an intermediate step.

          Code:
          sysuse auto
          net install gr0034
          graph drop _all
          
          sort foreign weight
          graph bar mpg trunk if foreign==1, over(weight, lab(angle(45))) name(g1)
          
          cap drop weight_
          gen weight_ = weight - 10
          twoway bar mpg weight_ if foreign==1, barw(10) legend(pos(6)) || bar trunk weight if foreign==1, barw(10) base(0) || scatter mpg weight if foreign==1, mla(make) mlabpos(12) mlabcolor(black) ms(none) name(g2)
          
          egen order = rank(weight) if foreign==1, unique
          gen order1=order+order-1
          gen order2=order+order
          labmask order1, values(weight)
          twoway bar mpg order1 if foreign==1, barw(0.7) legend(pos(6)) || bar trunk order2 if foreign==1, barw(0.7) base(0) || scatter mpg order1 if foreign==1, xlabel(1(4)44, valuelabel) mla(make) mlabpos(12) mlabcolor(black) ms(none) ytitle("") xtitle("") legend(row(1) label(3 "")) name(g3)
          Click image for larger version

Name:	g2.png
Views:	1
Size:	215.1 KB
ID:	1772882


          Click image for larger version

Name:	g3.png
Views:	1
Size:	250.0 KB
ID:	1772881

          Comment


          • #6
            Thank you both for answering, sometimes i need to produce something quick and at some point i settle with whatever that works even though its kind of frustrating not to get what you first imagined :-). Looking at the solution @Chen Samulsion it works really nice on this example, i substracted -0.3 from order2 such that bars per each "other" variable touch. Now i just have to see if this is feasible in a loop, as i need to produce many of these type of graphs, seems like it requires some manual adjusting when setting the order and barwidht ...

            Code:
            sysuse auto, clear
            graph drop _all
            
            egen order = rank(weight) if foreign==1, unique
            gen order1=order+order-1
            gen order2=order+order -0.3
            labmask order1, values(weight)
            twoway bar mpg order1 if foreign==1, barw(0.7) legend(pos(6)) || bar trunk order2 if foreign==1, barw(0.7) base(0) || scatter mpg order1 if foreign==1, xlabel(1(4)44, valuelabel) mla(make) mlabpos(12) mlabcolor(black) ms(none) ytitle("") xtitle("") legend(row(1) label(3 "")) name(g3)

            Comment


            • #7
              Dear Neko Novi, what do mean
              Now i just have to see if this is feasible in a loop, as i need to produce many of these type of graphs, seems like it requires some manual adjusting when setting the order and barwidth

              Comment


              • #8
                To impart some focus to the thread, here together are Neko's version from #6 and a multidot as suggested in #2. labmask is from the Stata Journal and multidot is from SSC.

                With all due allowance for parental affection, I know what I'd recommend.

                More crucially, putting mileage and trunk bars side by side is at best distracting and at worst fallacious. Bar heights refer to quite different units!

                The code is tweaked slightly to start from Stata 18 default.

                If you pursue #6 you need a way to make explicit that weight is being shown as well as mpg trunk make -- and to explain what the x axis labels mean (and to fend off accidents like the label "45").

                Code:
                sysuse auto, clear
                graph drop _all
                set scheme stcolor
                
                egen order = rank(weight) if foreign==1, unique
                gen order1=order+order-1
                gen order2=order+order -0.3
                labmask order1, values(weight)
                
                twoway bar mpg order1 if foreign==1, barw(0.7) legend(pos(6)) ///
                || bar trunk order2 if foreign==1, barw(0.7) base(0) ///
                || scatter mpg order1 if foreign==1, xlabel(1(4)44, valuelabel) ///
                mla(make) mlabpos(12) mlabcolor(black) ms(none) ytitle("") ///
                xtitle("") legend(row(1) label(3 "")) name(neko, replace)
                
                multidot weight mpg trunk if foreign, over(make) by(row(1)) name(njc, replace)
                Click image for larger version

Name:	neko.png
Views:	1
Size:	47.8 KB
ID:	1773091

                Click image for larger version

Name:	njc.png
Views:	1
Size:	63.9 KB
ID:	1773092

                Comment


                • #9
                  I wouldn't rule out some kind of parallel coordinates plot so long as each variable was scaled to dimensionless form, say by (value - mean) / SD or (value - min) / (max - min). In principle superimposed profiles convey the information directly; in practice they are often just a mess.
                  Last edited by Nick Cox; 19 Feb 2025, 13:47.

                  Comment

                  Working...
                  X