Announcement

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

  • Generating trend graph by group overlay with two figures side by side

    Hello all,

    I would like to generate two figures side-by-side (as below screenshot) which is divided by industrycode (byte, labeled by ind_label).
    Within each figure, I would like to overlay input_var by each firm size classes ("sizeclass", byte, labeled by sizeclasslabel).
    I apologize for complexity, but I could not show the data sample due to confidentiality issue and also there are restored in other laptop.
    I am unsure if my question was clear, but figure that I would like to generate looks like the below screenshot (detailed variables are different though).
    I tried using xtline input_var, overlay t(year) i(sizeclass) etc but I couldn't get what I wanted.

    Could someone pleeeaaseee help me?

    Thank you very much in advance.
    AC

    Click image for larger version

Name:	2025-02-19 오후 7.39.11.png
Views:	1
Size:	137.2 KB
ID:	1773095




  • #2
    It's perfectly understandable that your real data are confidential and can't be shown, but this common difficulty is answered in our FAQ Advice

    If your dataset is confidential, then provide a fake example instead.
    to which should be added (next revision)

    or use a standard Stata dataset.
    To get plots side by side like that you need a by() option. For a general discussion see

    SJ-20-4 gr0085 . The by() option of graph can work better than graph combine
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . N. J. Cox
    4/20 SJ 20(4):1016--1027 (no commands)
    describes whether to use the by() option of graph or
    graph combine for paneled figures

    To get a clickable link, go

    Code:
    . search gr0085, entry
    
    Search of official help files, FAQs, Examples, and Stata Journals
    
    SJ-20-4 gr0085  .  The by() option of graph can work better than graph combine
            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  N. J. Cox
            4/20    SJ 20(4):1016--1027                              (no commands)
            describes whether to use the by() option of graph or
            graph combine for paneled figures
    This example doesn't need much surgery, but other examples might need more.

    Code:
    webuse grunfeld, clear
    gen group = !mod(company, 2) if company <= 6
    label def group 0 odd 1 even
    label val group group  
    separate invest, by(company) veryshortlabel
    line invest1-invest6 year , by(group, note("")) ysc(log) ///
    yla(2000 1000 500 200 100 50 20) ytitle(Investment)
    Click image for larger version

Name:	oddeven.png
Views:	1
Size:	72.6 KB
ID:	1773113

    Comment


    • #3
      Nick Cox Thanks for your help, it's working well !!
      Just one additional question: how can I position that investment1-7 labels in the bottom of the figures?
      I tried many options but it's not working...

      Comment


      • #4
        I can't see any of your attempts to comment on your code, but indeed that is a little tricky. Code below and you can see the graph with legend moved by running the code. .

        In this particular example, I would prefer to remove the legend and use direct labelling. That may not work so well with longer identifying text. In short, direct labelling is ideal if (and nearly only if) text identifiers are concise and series are quite well separated.

        With more work you could arrange that text colours match line colours. Some people like to add direct labels at both ends of a time series.

        Further, the group labels odd and even are just for discussion purposes and should not appear in a presentation, paper or report. The intent is only to draw attention to a very small trick. Here the series are ranked in general level and putting 1 3 5 in one panel and 2 4 6 in another increases the separation between series. Other way round, there could be strong (e.g. economic) reasons for placing particular series next to each other in a graphical panel (sometimes called facet).

        I'll add that whenever series are very close, as in #1, it sometimes helps to take one series as reference and plot the others as differences from it (or as ratios on logarithmic scale).

        See also

        Code:
        SJ-21-2 gr0087  . . Front-and-back plots to ease spaghetti and paella problems
                (help fabplot if installed) . . . . . . . . . . . . . . . .  N. J. Cox
                Q2/21   SJ 21(2):539--554
                explores front-and-back plots, in which each subset of data
                is shown separately with the other subsets as backdrop
        
        SJ-19-4 gr0080  . . . . . .  Some simple devices to ease the spaghetti problem
                . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  N. J. Cox
                Q4/19   SJ 19(4):989--1008                               (no commands)
                gives guidance on avoiding the spaghetti problem in graphics
                (where multiple time series or other functional traces show
                mostly a tangled mess)
        Code:
        webuse grunfeld, clear
        gen group = !mod(company, 2) if company <= 6
        label def group 0 odd 1 even
        label val group group  
        separate invest, by(company) veryshortlabel
        
        line invest1-invest6 year , by(group, note("") legend(pos(6))) ysc(log) ///
        yla(2000 1000 500 200 100 50 20) ytitle(Investment) legend(row(2))
        
        
        line invest1-invest6 year , by(group, note("") legend(off)) ysc(log) ///
        yla(2000 1000 500 200 100 50 20) ytitle(Investment) ///
        || scatter invest year if year == 1954, ms(none) mla(company) mlabsize(large) mlabc(black)
        Click image for larger version

Name:	invest.png
Views:	1
Size:	74.6 KB
ID:	1773132

        Last edited by Nick Cox; 20 Feb 2025, 02:26.

        Comment


        • #5
          How does one move the legend to the bottom, though?

          . sysuse auto, clear
          . twoway (scatter mpg headroom) (function y=20, range(headroom)), by(foreign, note("")) legend(row(1) pos(6) ring(100))

          Stata just ignores the legend placement here.

          Comment


          • #6
            lucas reddinger, yes, it is indeed complicated. I guess you used -stcolor- scheme, and if you use -s2color-, the problem will disappear. Fortunately, you can modify this under -stcolor- scheme. And the trick lies in the help by_option##remarks7.

            Code:
            sysuse auto, clear
            twoway (scatter mpg headroom) (function y=20, range(headroom)), by(foreign, note("")) legend(row(1) pos(6) ring(100)) scheme(s2color) name(g1, replace)
            twoway (scatter mpg headroom) (function y=20, range(headroom)), by(foreign, note("")) legend(row(1) pos(6) ring(100)) scheme(stcolor) name(g2, replace)
            twoway (scatter mpg headroom) (function y=20, range(headroom)), by(foreign, note("") legend(row(1) pos(6) ring(100))) scheme(stcolor) name(g3, replace)
            twoway (scatter mpg headroom) (function y=20, range(headroom)), by(foreign, note("") legend(pos(6) ring(100))) legend(row(1))scheme(stcolor) name(g4, replace)
            twoway (scatter mpg headroom) (function y=20, range(headroom)), by(foreign, note("") legend(on row(1) pos(6) ring(100))) legend(row(1) pos(6) ring(100)) scheme(stcolor) name(g5, replace)
            If you wish to modify or suppress the default legend, you must do that differently when by() is specified.
            For instance, legend(off) -- see [G-3] legend_options -- will suppress the legend, yet typing

            . line y1 y2 x, by(group) legend(off)

            will not have the intended effect. The legend(off) will seemingly be ignored. You must instead type

            . line y1 y2 x, by(group, legend(off))

            We moved legend(off) inside the by().

            Remember that by() repeats the graph command. If you think carefully, you will realize that the legend
            never was displayed at the bottom of the individual plots. It is instructive to type

            . line y1 y2 x, legend(on) by(group)

            This graph will have many legends: one underneath each of the plots in addition to the overall legend at
            the bottom of the graph! by() works exactly as advertised: it repeats the entire graph command for each
            value of group.

            In any case, it is the overall legend() that we want to suppress, and that is why we must specify
            legend(off) inside the by() option; this is the same issue as the one discussed under Treatment of titles
            above.

            The issue becomes a little more complicated when, rather than suppressing the legend, we wish to modify
            the legend's contents or position. Then the legend() option to modify the contents is specified outside
            the by() and the legend() option to modify the location is specified inside.
            See Use of legends with by()
            in [G-3] legend_options.

            Comment


            • #7
              lucas reddinger Please study #5 again and do try running the code. I showed code for two graphs, and the first code showed a legend at the bottom. I just didn't show you the graph -- because I think the second graph is better for these data.. Here is the code again and now the graph is shown.

              Code:
              webuse grunfeld, clear
              gen group = !mod(company, 2) if company <= 6
              label def group 0 odd 1 even
              label val group group  
              separate invest, by(company) veryshortlabel
              
              line invest1-invest6 year , by(group, note("") legend(pos(6))) ysc(log) ///
              yla(2000 1000 500 200 100 50 20) ytitle(Investment) legend(row(2)) scheme(stcolor)
              I've now made explicit that I am using stcolor, but I get equivalent results with say s1color or s2color.

              Click image for larger version

Name:	legend_bottom.png
Views:	1
Size:	69.2 KB
ID:	1773486

              Comment


              • #8
                Thanks to you both! -help by_option- is a good read...

                Comment

                Working...
                X