Announcement

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

  • Time axis labels, ticks and dividers for quarterly and other series

    A data example posted by Aziz Essouaied at https://www.statalist.org/forums/for...-tsset-command serves nicely to illustrate various small points of graphical technique.

    The code posted here is indicative, not definitive. On the contrary, small details are what this is all about and you may want choices different in detail, or may need any such for your own data.

    Code:
    * Example generated by -dataex-. To install: ssc install dataex
    clear
    input str10 Trimester float Regulated_Savings
    "31/03/2012" 602.745
    "30/06/2012" 610.186
    "30/09/2012" 618.868
    "31/12/2012" 649.851
    "31/03/2013" 663.513
    "30/06/2013" 671.947
    "30/09/2013" 676.439
    "31/12/2013" 675.125
    "31/03/2014" 680.735
    "30/06/2014" 684.159
    "30/09/2014" 685.923
    "31/12/2014" 685.712
    "31/03/2015" 691.676
    "30/06/2015" 695.007
    "30/09/2015" 696.561
    "31/12/2015" 698.123
    "31/03/2016" 703.648
    "30/06/2016" 707.075
    "30/09/2016" 710.701
    "31/12/2016" 714.973
    "31/03/2017" 719.871
    "30/06/2017"  725.44
    "30/09/2017" 729.505
    "31/12/2017" 733.054
    "31/03/2018"  739.07
    "30/06/2018" 742.654
    "30/09/2018" 745.892
    "31/12/2018" 751.387
    "31/03/2019" 758.858
    "30/06/2019"  763.99
    "30/09/2019" 767.992
    "31/12/2019" 771.523
    "31/03/2020" 781.125
    "30/06/2020"  799.21
    "30/09/2020" 806.111
    "31/12/2020" 813.715
    "31/03/2021" 825.781
    "30/06/2021" 832.057
    "30/09/2021"  834.94
    "31/12/2021"  833.74
    "31/03/2022" 845.136
    "30/06/2022" 848.772
    "30/09/2022"  862.34
    "31/12/2022" 874.131
    "31/03/2023" 902.552
    "30/06/2023" 914.995
    "30/09/2023" 926.074
    "31/12/2023" 935.543
    "31/03/2024"  942.37
    "30/06/2024" 946.971
    "30/09/2024" 953.214
    "31/12/2024" 955.681
    end
    
    gen QDate = qofd(daily(Trimester, "DMY"))
    format QDate %tq 
    line Regulated_Savings QDate
    
    forval y = 2012/2024 {
        local mid = yq(`y', 2) + 0.5 
        local mids `mids' `mid' "`y'"
        local end = yq(`y', 4) + 0.5 
        local ends `ends' `end'
    }
    
    twoway connected Regulated_Savings QDate, xla(`mids', tlength(0)) xline(`ends', lc(gs12) lw(vthin) lp(solid)) xtick(`ends', tlength(*4)) xtitle("") ytitle(better title needed here with units of measurement)
    Click image for larger version

Name:	time_interval.png
Views:	1
Size:	56.2 KB
ID:	1779990


    Something like this may help particularly with quarterly or monthly data. occasionally with data with some other time basis.

    Here quarters are intervals, but we may choose to show them as data points.

    Years are intervals but conversely we do often want to show them as such. So in the code there is a loop over years setting up

    axis labels to be shown in the middle of each year (between quarters 2 and 3)

    ticks and divider lines to be shown after the end of each year (between quarters 4 and 1)

    That removes awkward annotation such as "2012q1". But the years should not be shown with accompanying ticks (or grid lines -- in some graph schemes you may need to fight off grid lines).

    Other way round, you may want, as in the code, ticks at year ends and to make them longer -- or you may want to omit them all together. Note in passing that removing ticks, setting their length to zero, and setting their colour to none are three different techniques.

    You may want dividers between years. When I do want dividers I usually want them to be very thin and very pale. There could be exceptions. If there was a change of government or policy or some other sudden or important change, you may want the opposite.

    In most people's education that was some teacher who marked down graphs severely if some axis was explained poorly (or not at all). That teacher was more right than wrong, but for graphs like these we surely don't need some dopey x axis title like Date or Year. Or so I suggest.

    This is just a recycling of points made elsewhere, but someimes advice bears repetition.

    Here seasonality appears muted but an example in one paper https://journals.sagepub.com/doi/pdf...867X0800700410 shows a more seasonal pattern.

    Tick trickery was reviewed at https://journals.sagepub.com/doi/pdf...36867X19874264




  • #2
    Nick Cox Your help is amazing, thanks very much for it. What you've exposed does really help in working with quarterly data and with making the graph readable and easy to analyse. The thing with grid lines is that I tend to always use them in my graphs to make is easier for those who will read it to pinpoint a specific number or data on the graph, since, when I used to be a kid, I used to use a ruler on graphs o read a given point's value (which is kind of funny). Anyway, the data table is always available for those who demand it if they are looking for a specific variable, and also, having grid lines for the quarters would make the graph busy and unreadable.
    Agains, thanks for the clarifications

    Comment


    • #3
      Nick Cox Your help and explanation are very much useful, that I actually would love it if you could help with another data that seems to be comparable to the first data example you've used here.

      Again, I'm working with the 13.1 version of Stata. Here's my data:

      Code:
      * Example generated by -dataex-. To install: ssc install dataex
      clear
      input str7 Period float Old_Housing_Price_Index
      "T1 1998" -1.8
      "T2 1998"  2.5
      "T3 1998"  2.5
      "T4 1998"  -.5
      "T1 1999"  1.3
      "T2 1999"  2.5
      "T3 1999"  4.1
      "T4 1999"   .1
      "T1 2000"  1.7
      "T2 2000"    3
      "T3 2000"  3.8
      "T4 2000"  -.5
      "T1 2001"  1.4
      "T2 2001"  3.3
      "T3 2001"  3.2
      "T4 2001"  -.1
      "T1 2002"    1
      "T2 2002"  3.5
      "T3 2002"  4.5
      "T4 2002"   .9
      "T1 2003"  1.9
      "T2 2003"  3.9
      "T3 2003"  4.5
      "T4 2003"  1.9
      "T1 2004"  3.3
      "T2 2004"  4.2
      "T3 2004"  5.2
      "T4 2004"  2.4
      "T1 2005"  2.9
      "T2 2005"  4.4
      "T3 2005"    5
      "T4 2005"  1.8
      "T1 2006"  2.4
      "T2 2006"  3.1
      "T3 2006"  3.4
      "T4 2006"   .7
      "T1 2007"   .7
      "T2 2007"  1.8
      "T3 2007"  2.4
      "T4 2007"   .7
      "T1 2008"  -.7
      "T2 2008"    0
      "T3 2008"   .5
      "T4 2008" -3.6
      "T1 2009" -4.4
      "T2 2009" -1.8
      "T3 2009"  1.9
      "T4 2009"   .2
      "T1 2010"   .9
      "T2 2010"  2.1
      "T3 2010"  3.2
      "T4 2010"  1.1
      "T1 2011"   .4
      "T2 2011"  2.1
      "T3 2011"  2.3
      "T4 2011" -1.2
      "T1 2012" -1.4
      "T2 2012"    0
      "T3 2012"   .9
      "T4 2012" -1.6
      "T1 2013" -1.3
      "T2 2013"  -.2
      "T3 2013"   .8
      "T4 2013" -1.2
      "T1 2014" -1.3
      "T2 2014"   .3
      "T3 2014"   .7
      "T4 2014" -2.3
      "T1 2015" -1.2
      "T2 2015"   .1
      "T3 2015"  1.6
      "T4 2015"  -.9
      "T1 2016"  -.4
      "T2 2016"   .4
      "T3 2016"  2.2
      "T4 2016"  -.7
      "T1 2017"   .5
      "T2 2017"    1
      "T3 2017"  2.4
      "T4 2017"  -.7
      "T1 2018"   .2
      "T2 2018"   .9
      "T3 2018"  2.5
      "T4 2018"  -.4
      "T1 2019"    0
      "T2 2019"    1
      "T3 2019"  2.5
      "T4 2019"   .2
      "T1 2020"  1.1
      "T2 2020"  1.7
      "T3 2020"  2.1
      "T4 2020"  1.3
      "T1 2021"   .7
      "T2 2021"    2
      "T3 2021"  3.3
      "T4 2021"    1
      "T1 2022"   .9
      "T2 2022"  1.6
      "T3 2022"  2.9
      "T4 2022"  -.8
      end
      The first variable is a time variable defined by trimesters (or quarters again, 3 months) from 1998 to 2024 (the example shows the data until 2022). The second variable is an Index of Old Houses' Prices in a given country. It's the same goal: To draw a time graph showing the historical evolution of that index, I would love it if the same technic is used to have the x axis of time defined by the years, yet I would like to have the points of the quarters or trimesters.

      Thanks again for the help.

      Comment


      • #4
        This is just a minor variation on several questions you have asked before, so you really should be able to work It out.

        Comment


        • #5
          Nick Cox I really tried to adapt your suggested code to my data, I've ended reformulating the Period variable as such:

          Code:
          * Example generated by -dataex-. To install: ssc install dataex
          clear
          input str10 period float old_housing_price_index
          "31/03/1998" -1.8
          "30/06/1998"  2.5
          "30/09/1998"  2.5
          "31/12/1998"  -.5
          "31/03/1999"  1.3
          "30/06/1999"  2.5
          "30/09/1999"  4.1
          "31/12/1999"   .1
          "31/03/2000"  1.7
          "30/06/2000"    3
          "30/09/2000"  3.8
          "31/12/2000"  -.5
          "31/03/2001"  1.4
          "30/06/2001"  3.3
          "30/09/2001"  3.2
          "31/12/2001"  -.1
          "31/03/2002"    1
          "30/06/2002"  3.5
          "30/09/2002"  4.5
          "31/12/2002"   .9
          "31/03/2003"  1.9
          "30/06/2003"  3.9
          "30/09/2003"  4.5
          "31/12/2003"  1.9
          "31/03/2004"  3.3
          "30/06/2004"  4.2
          "30/09/2004"  5.2
          "31/12/2004"  2.4
          "31/03/2005"  2.9
          "30/06/2005"  4.4
          "30/09/2005"    5
          "31/12/2005"  1.8
          "31/03/2006"  2.4
          "30/06/2006"  3.1
          "30/09/2006"  3.4
          "31/12/2006"   .7
          "31/03/2007"   .7
          "30/06/2007"  1.8
          "30/09/2007"  2.4
          "31/12/2007"   .7
          "31/03/2008"  -.7
          "30/06/2008"    0
          "30/09/2008"   .5
          "31/12/2008" -3.6
          "31/03/2009" -4.4
          "30/06/2009" -1.8
          "30/09/2009"  1.9
          "31/12/2009"   .2
          "31/03/2010"   .9
          "30/06/2010"  2.1
          "30/09/2010"  3.2
          "31/12/2010"  1.1
          "31/03/2011"   .4
          "30/06/2011"  2.1
          "30/09/2011"  2.3
          "31/12/2011" -1.2
          "31/03/2012" -1.4
          "30/06/2012"    0
          "30/09/2012"   .9
          "31/12/2012" -1.6
          "31/03/2013" -1.3
          "30/06/2013"  -.2
          "30/09/2013"   .8
          "31/12/2013" -1.2
          "31/03/2014" -1.3
          "30/06/2014"   .3
          "30/09/2014"   .7
          "31/12/2014" -2.3
          "31/03/2015" -1.2
          "30/06/2015"   .1
          "30/09/2015"  1.6
          "31/12/2015"  -.9
          "31/03/2016"  -.4
          "30/06/2016"   .4
          "30/09/2016"  2.2
          "31/12/2016"  -.7
          "31/03/2017"   .5
          "30/06/2017"    1
          "30/09/2017"  2.4
          "31/12/2017"  -.7
          "31/03/2018"   .2
          "30/06/2018"   .9
          "30/09/2018"  2.5
          "31/12/2018"  -.4
          "31/03/2019"    0
          "30/06/2019"    1
          "30/09/2019"  2.5
          "31/12/2019"   .2
          "31/03/2020"  1.1
          "30/06/2020"  1.7
          "30/09/2020"  2.1
          "31/12/2020"  1.3
          "31/03/2021"   .7
          "30/06/2021"    2
          "30/09/2021"  3.3
          "31/12/2021"    1
          "31/03/2022"   .9
          "30/06/2022"  1.6
          "30/09/2022"  2.9
          "31/12/2022"  -.8
          end
          The code worked just fine. The thing is that I don't have that much knowledge in what comes to graph options, by which I mean that I have got this result that's attached to this post. Clearly it is a problem of options.

          Any help please? With many thanks
          Attached Files

          Comment


          • #6
            Please review the FAQ Advice for basic protocol here.

            .gph attachments are deprecated: .png attachments are requested.

            What command did you use? What's the specific problem? There isn't here a clear and precise question that anyone is likely to be able to answer.

            Comment


            • #7
              Nick Cox Sorry. Here attached is the png format of the same graph.

              The problem is in the options of the twoway connected command.

              I've used the same code you've suggested, just changed the variables that's all:

              gen QDate = qofd(daily(period, "DMY"))
              format QDate %tq
              line old_housing_price_index QDate

              forval y = 2012/2024 {
              local mid = yq(`y', 2) + 0.5
              local mids `mids' `mid' "`y'"
              local end = yq(`y', 4) + 0.5
              local ends `ends' `end'
              }

              twoway connected old_housing_price_index QDate, xla(`mids', tlength(0)) xline(`ends', lc(gs12) lw(vthin) lp(solid)) xtick(`ends', tlength(*4)) xtitle("") ytitle(better title needed here with units of measurement)

              I just don't thave the knowledge to adapt the twoway command options to my data in order to have an organized x axis, I receive a result with the years which are offset from the graph.
              Attached Files

              Comment


              • #8
                Manifestly these data start at 1998 and end in 2022, so you need to ask for year labels accordingly in the loop. It is possible that you need a different recipe for the axis labels, such as showing 98 to 22, not 1998 to 2022.

                See the paper on fun and fluency with functions on functions you need to know. I am on my phone but you should be able to find a link,

                Seasonality is pronounced here, so

                Code:
                search cycleplot
                for an alternative display.



                Last edited by Nick Cox; 25 Jul 2025, 04:20.

                Comment


                • #9
                  Nick Cox You are absolutely right about the years, I've just changed them to 1998-2024 and it worked.

                  Again, thanks for the help!

                  Comment


                  • #10
                    This thread is getting difficult to navigate. Blame that on me too!

                    #1 is a question answered by #2.

                    The rest of the thread starts at #3. Note that the data in #3 and #5 are not the same. Aziz changed the name of the outcome variable and also changed a string quarterly date to a string daily date. That wasn't necessary.

                    The problem with a quarterly data string like "T1 1998" is only that the T makes no sense to Stata's date functions. This is precisely where the paper alluded to in #8 tells you what you need to know.


                    Code:
                    SJ-11-3 dm0058  . . . . . . . . Speaking Stata: Fun and fluency with functions
                            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  N. J. Cox
                            Q3/11   SJ 11(3):460--471                                (no commands)
                            a tour of easily missed or underestimated Stata functions

                    https://journals.sagepub.com/doi/pdf...867X1101100308

                    You could just replace each instance of T by nothing using subinstr() or you could tell Stata to ignore such instances using substr() as done here.

                    The graphs here explore two suggestions: two-digit year labels and application of cycleplot.

                    Code:
                    SJ-10-1 pr0051  . . . . . . . . . . . . Stata tip 85: Looping over nonintegers
                            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  N. J. Cox
                            Q1/10   SJ 10(1):160--163                                (no commands)
                            tip on using forvalues to loop over numbers
                    
                    SJ-24-4 gr0025_1  . . . . . . . .  Software update for cycleplot and sliceplot
                            (help cycleplot, sliceplot if installed)  . . . . . . . . .  N. J. Cox
                            Q4/24   SJ 24(4):788--789
                            cycleplot now supports the addplot() option;
                            sliceplot help file now documents an alternative approach
                    
                    SJ-6-3  gr0025  . . . . . . . . . . . . Speaking Stata: Graphs for all seasons
                            (help cycleplot, sliceplot if installed)  . . . . . . . . .  N. J. Cox
                            Q3/06   SJ 6(3):397--419
                            illustrates producing graphs showing time-series seasonality
                    Code:
                    * Example generated by -dataex-. To install: ssc install dataex
                    clear
                    input str7 Period float old_housing_price_index
                    "T1 1998" -1.8
                    "T2 1998"  2.5
                    "T3 1998"  2.5
                    "T4 1998"  -.5
                    "T1 1999"  1.3
                    "T2 1999"  2.5
                    "T3 1999"  4.1
                    "T4 1999"   .1
                    "T1 2000"  1.7
                    "T2 2000"    3
                    "T3 2000"  3.8
                    "T4 2000"  -.5
                    "T1 2001"  1.4
                    "T2 2001"  3.3
                    "T3 2001"  3.2
                    "T4 2001"  -.1
                    "T1 2002"    1
                    "T2 2002"  3.5
                    "T3 2002"  4.5
                    "T4 2002"   .9
                    "T1 2003"  1.9
                    "T2 2003"  3.9
                    "T3 2003"  4.5
                    "T4 2003"  1.9
                    "T1 2004"  3.3
                    "T2 2004"  4.2
                    "T3 2004"  5.2
                    "T4 2004"  2.4
                    "T1 2005"  2.9
                    "T2 2005"  4.4
                    "T3 2005"    5
                    "T4 2005"  1.8
                    "T1 2006"  2.4
                    "T2 2006"  3.1
                    "T3 2006"  3.4
                    "T4 2006"   .7
                    "T1 2007"   .7
                    "T2 2007"  1.8
                    "T3 2007"  2.4
                    "T4 2007"   .7
                    "T1 2008"  -.7
                    "T2 2008"    0
                    "T3 2008"   .5
                    "T4 2008" -3.6
                    "T1 2009" -4.4
                    "T2 2009" -1.8
                    "T3 2009"  1.9
                    "T4 2009"   .2
                    "T1 2010"   .9
                    "T2 2010"  2.1
                    "T3 2010"  3.2
                    "T4 2010"  1.1
                    "T1 2011"   .4
                    "T2 2011"  2.1
                    "T3 2011"  2.3
                    "T4 2011" -1.2
                    "T1 2012" -1.4
                    "T2 2012"    0
                    "T3 2012"   .9
                    "T4 2012" -1.6
                    "T1 2013" -1.3
                    "T2 2013"  -.2
                    "T3 2013"   .8
                    "T4 2013" -1.2
                    "T1 2014" -1.3
                    "T2 2014"   .3
                    "T3 2014"   .7
                    "T4 2014" -2.3
                    "T1 2015" -1.2
                    "T2 2015"   .1
                    "T3 2015"  1.6
                    "T4 2015"  -.9
                    "T1 2016"  -.4
                    "T2 2016"   .4
                    "T3 2016"  2.2
                    "T4 2016"  -.7
                    "T1 2017"   .5
                    "T2 2017"    1
                    "T3 2017"  2.4
                    "T4 2017"  -.7
                    "T1 2018"   .2
                    "T2 2018"   .9
                    "T3 2018"  2.5
                    "T4 2018"  -.4
                    "T1 2019"    0
                    "T2 2019"    1
                    "T3 2019"  2.5
                    "T4 2019"   .2
                    "T1 2020"  1.1
                    "T2 2020"  1.7
                    "T3 2020"  2.1
                    "T4 2020"  1.3
                    "T1 2021"   .7
                    "T2 2021"    2
                    "T3 2021"  3.3
                    "T4 2021"    1
                    "T1 2022"   .9
                    "T2 2022"  1.6
                    "T3 2022"  2.9
                    "T4 2022"  -.8
                    end
                    
                    gen QDate = quarterly(substr(Period, 2, .), "QY")
                    
                    gen quarter = real(substr(Period, 2, 1))
                    
                    gen year = real(substr(Period, -4, 4))
                    
                    line old_housing_price_index QDate
                    
                    forval y = 1998/2022 {
                    local mid = yq(`y', 2) + 0.5
                    local show : di %02.0f mod(`y', 100)
                    local mids `mids' `mid' "`show'"
                    local end = yq(`y', 4) + 0.5
                    local ends `ends' `end'
                    }
                    
                    twoway connected old_housing_price_index QDate, xla(`mids', tlength(0)) xline(`ends', lc(gs12) lw(vthin) lp(solid)) xtick(`ends', tlength(*4)) xtitle("") name(G1, replace)
                    
                    cycleplot old_housing_price_index quarter year, length(4) name(G2, replace)
                    I don't know how Aziz made year labels 1998 to 2022 legible.

                    There is endless room for doing something different. Perhaps the long ticks in the first graph are dispensable. I guess most researchers would just go for a standard time series plot here, but the cycle plot shows the seasonality more clearly.


                    Click image for larger version

Name:	housing1.png
Views:	1
Size:	156.7 KB
ID:	1780335
                    Click image for larger version

Name:	housing2.png
Views:	1
Size:	70.6 KB
ID:	1780336

                    Comment

                    Working...
                    X