Announcement

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

  • dot plot showing group means on the same line for multiple variables

    Dear Stataforum,

    Does anyone know how to produce a graph that looks like Nick's dot plot example using multiple outcome variables and only one "over" variable?

    The goal is to plot two group means (with different markers for the two groups) on each line of a dot plot that examines the means for multiple variables.
    The over() and by() options seem to be headed in the right direction, but I can't figure out how to put the two group means for each variable on the same line.

    I have pasted Nick's code below along with two of my failed attempts.

    In the graph I wish to make, all the variables have the same range of possible values so a single axis will work just fine.
    This is not the case in the examples below using mvalue, invest, and kstock, so the example may present some difficulties that I will not need to address.

    Thanks,

    Jeremy

    Code:
    webuse grunfeld, clear 
    
    *Nick's code: two means on each horizontal line with different markers for the two years
    graph dot (asis) mvalue if inlist(year, 1953, 1954), over(year) over(company, sort(1) desc) ///
    marker(1, ms(Oh)) marker(2, ms(+)) asyvars /// 
    linetype(line) lines(lcolor(gs12) lw(vthin)) ytitle(Market value (units???)) ysc(alt)
    
    *What if I have multiple variables (mvalue invest kstock) rather than one (mvalue)
    *and care about year differences but not company differences?
    
    *one mean on each horizontal line but with two panels
    graph dot mvalue invest kstock if inlist(year, 1953, 1954), ascat over(year) ///
    marker(1, ms(Oh)) marker(2, ms(+)) asyvars /// 
    linetype(line) lines(lcolor(gs12) lw(vthin)) ytitle(Market value (units???)) ysc(alt)
    
    *one mean on each horizontal line but with two subgraphs
    graph dot mvalue invest kstock if inlist(year, 1953, 1954), ascat by(year) ///
    marker(1, ms(Oh)) marker(2, ms(+)) asyvars /// 
    linetype(line) lines(lcolor(gs12) lw(vthin)) ytitle(Market value (units???)) ysc(alt)

  • #2
    Simple example you can work on.

    Code:
    webuse grunfeld, clear
    *one mean on each horizontal line but with two panels
    rename (invest mvalue kstock) var=
    reshape long var, i(company year) j(which) string
    collapse var, by(which year)
    separate var, by(which) veryshortlabel
    set scheme s1color
    tw dot var? year, ms(Oh Oh Oh) horizontal ylab(1935/1954, angle(horiz)) ytitle("")
    Click image for larger version

Name:	Graph.png
Views:	1
Size:	96.4 KB
ID:	1626813

    Last edited by Andrew Musau; 08 Sep 2021, 14:58.

    Comment


    • #3
      Actually, the reshape is totally unnecessary in #2

      Code:
      collapse invest mvalue kstock, by(year)
      tw dot invest mvalue kstock year, ms(Oh Oh Oh) horizontal ylab(1935/1954, angle(horiz)) ytitle("")
      will do.

      Comment


      • #4
        Thank you Andrew! That is a very elegant solution.

        However, I would like the y-axis to list multiple variables (in the grunfeld data these could be: invest mvalue kstock) and I would like the legend to list the different groups (in the grunfeld data these could be: time=1-10 vs time=11-20). Because I don't know how to do this with code, I have taken the graph you made and modified it to show the kind of thing I want to create.
        Sorry I wasn't clearer in my original description.

        Thanks again for your help.

        Jeremy

        Click image for larger version

Name:	dotgraph.jpg
Views:	1
Size:	34.0 KB
ID:	1626823

        Comment


        • #5
          It should be just a matter of manipulating your data.

          Code:
          webuse grunfeld, clear
          gen periods= floor(time/10)
          collapse invest mvalue kstock, by(periods)
          rename (invest mvalue kstock) var=
          reshape long var, i(period) j(which) string
          reshape wide var, i(which) j(period)
          set scheme s1color
          gr dot var?, over(which) marker(1, ms(Oh)) marker(2, ms(+)) ///
          marker(3, ms(T)) leg(order(1 "Group 1" 2 "Group 2" 3 "Group 3"))
          Click image for larger version

Name:	Graph.png
Views:	1
Size:	19.8 KB
ID:	1626857

          Comment


          • #6
            Wow! I never would have arrived at that solution. It is perfect. Thank you Andrew!!

            Comment


            • #7
              Hello Andrew Musau, I have a similar problem, I trust you could help me.

              Please refer to the data below:

              Code:
              * Example generated by -dataex-. To install: ssc install dataex
              clear
              input str3 isocode float(rmspe_ratio rmspe_ratio_nontrad rmspe_ratio_trad)
              "AUS" 11.215573  8.983412   11.23055
              "AUT"  19.76916 2.7288115  14.436868
              "BEL" 1.8012733 31.644915   6.464915
              "CAN" 35.417046   20.6397   15.83248
              "DEU"  52.19558  6.149171  11.861136
              "DNK" 103.34541 14.086783  14.331928
              "ESP" 123.92865 9.0475235 2153353728
              "FIN"  2.507858 4.1966157   2.919689
              "FRA" 11.015525 4.1422396  14.913485
              "GBR"  6.136033 1.2584594  33.862404
              "GRC"  2.435744 1.7185236   7.566734
              "IRL"  8.025526  7.625298  13.901612
              "ITA" 11.424737 1.2656703   38.77885
              "JPN"  5.901664  3.493253  10.975296
              "KOR"   5.65565  6.419165  4.5806394
              "LUX"  .7984496 1.0085338   .6254423
              "MEX" 3.7935975   1.56676   10.83889
              "NLD"  7.257888  15.28863   78.49872
              "PRT"  12.59457  15.91689  4.6817436
              "SWE"  6.016787 11.646316  15.599452
              "USA"  8.554289 4.4847775   7.778163
              end
              I would like to have a dot plot in which the yaxis contains the the countries (capture by variable "isocode"), while variables rmspe_ratio, rmspe_ratio_nontrad, and rmspe_ratio_trad should on the x-axis.
              Your help will be highly appreciated.

              Comment


              • #8
                This example requires Nick Cox's myaxis, which is available from SSC. To install it type in Stata: ssc install myaxis

                Code:
                clear
                input str3 isocode float(rmspe_ratio rmspe_ratio_nontrad rmspe_ratio_trad)
                "AUS" 11.215573  8.983412   11.23055
                "AUT"  19.76916 2.7288115  14.436868
                "BEL" 1.8012733 31.644915   6.464915
                "CAN" 35.417046   20.6397   15.83248
                "DEU"  52.19558  6.149171  11.861136
                "DNK" 103.34541 14.086783  14.331928
                "ESP" 123.92865 9.0475235 21.53353728
                "FIN"  2.507858 4.1966157   2.919689
                "FRA" 11.015525 4.1422396  14.913485
                "GBR"  6.136033 1.2584594  33.862404
                "GRC"  2.435744 1.7185236   7.566734
                "IRL"  8.025526  7.625298  13.901612
                "ITA" 11.424737 1.2656703   38.77885
                "JPN"  5.901664  3.493253  10.975296
                "KOR"   5.65565  6.419165  4.5806394
                "LUX"  .7984496 1.0085338   .6254423
                "MEX" 3.7935975   1.56676   10.83889
                "NLD"  7.257888  15.28863   78.49872
                "PRT"  12.59457  15.91689  4.6817436
                "SWE"  6.016787 11.646316  15.599452
                "USA"  8.554289 4.4847775   7.778163
                end
                
                myaxis y = isocode, sort(mean rmspe_ratio)
                
                scatter y rmspe_ratio ||                  ///
                scatter y rmspe_ratio_nontrad ||          ///
                scatter y rmspe_ratio_trad ,              ///
                    ylab(1/21, val angle(0))              ///
                    legend(order( 1 "rmspe_ratio"         ///
                                  2 "rmspe_ratio_nontrad" ///
                                  3 "rmspe_ratio_trad"))
                Last edited by Maarten Buis; 17 Nov 2021, 03:57.
                ---------------------------------
                Maarten L. Buis
                University of Konstanz
                Department of history and sociology
                box 40
                78457 Konstanz
                Germany
                http://www.maartenbuis.nl
                ---------------------------------

                Comment


                • #9
                  That value of 2 billion or so

                  2153353728

                  is either incorrect or correct and very difficult to show consistently with other values. Even otherwise ratios that are positive usually call for logarithmic scale and I think that applies here. I couldn't get ysc(log) to work with graph dot even with exclude0 but here is a work-around:


                  Code:
                  * Example generated by -dataex-. To install: ssc install dataex
                  clear
                  input str3 isocode float(rmspe_ratio rmspe_ratio_nontrad rmspe_ratio_trad)
                  "AUS" 11.215573  8.983412   11.23055
                  "AUT"  19.76916 2.7288115  14.436868
                  "BEL" 1.8012733 31.644915   6.464915
                  "CAN" 35.417046   20.6397   15.83248
                  "DEU"  52.19558  6.149171  11.861136
                  "DNK" 103.34541 14.086783  14.331928
                  "ESP" 123.92865 9.0475235 2153353728
                  "FIN"  2.507858 4.1966157   2.919689
                  "FRA" 11.015525 4.1422396  14.913485
                  "GBR"  6.136033 1.2584594  33.862404
                  "GRC"  2.435744 1.7185236   7.566734
                  "IRL"  8.025526  7.625298  13.901612
                  "ITA" 11.424737 1.2656703   38.77885
                  "JPN"  5.901664  3.493253  10.975296
                  "KOR"   5.65565  6.419165  4.5806394
                  "LUX"  .7984496 1.0085338   .6254423
                  "MEX" 3.7935975   1.56676   10.83889
                  "NLD"  7.257888  15.28863   78.49872
                  "PRT"  12.59457  15.91689  4.6817436
                  "SWE"  6.016787 11.646316  15.599452
                  "USA"  8.554289 4.4847775   7.778163
                  end
                  
                  foreach v of var *ratio* {
                      gen log`v' = log10(`v')
                      label var log`v' "`v'"
                  }
                  
                  graph dot (asis) log* if isocode != "ESP", over(isocode, sort(1)) ///
                  yla(0 "1" 1 "10" `=log10(3)' "3" `=log10(30)' "30" 2 "100") ///
                  scheme(s1color) marker(1, ms(Oh)) marker(2, ms(+)) marker(3, ms(Th)) legend(pos(12) row(1))
                  Click image for larger version

Name:	ratio.png
Views:	1
Size:	65.0 KB
ID:	1636892




                  Notes:

                  Alphabetical order is less valuable usually than sorting on one of the outcomes shown. Which outcome is up to you. Maarten Buis makes the same point.

                  The legend would be improved by better text.

                  With
                  graph dot I find that the dotted grid is often degraded on export to other software so I tend to use very thin grey grid lines instead.

                  I just missed out Spain, but there should be a better fix, like a more plausible value for the rogue ratio.
                  Last edited by Nick Cox; 17 Nov 2021, 04:42.

                  Comment


                  • #10
                    Thank you very much Nick Cox and Maarten Buis
                    This is exactly what I needed.
                    And thank you for the hint to tweak the 2bn value.

                    Comment

                    Working...
                    X