Announcement

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

  • Plotting multiple time series

    The immediate stimulus for this thread is a recent question

    http://www.statalist.org/forums/foru...fferent-scales

    but the solution here may not be what was wanted there. In any case the focus of this thread is code I now offer and, as it were, my version of the problem.

    It's like this:

    * You want a graph of two or more time series, which may have very different units of measurement and/or magnitudes of values.

    * tsline or xtline or a direct line versus your time variable doesn't do a very good job. That is, the command is doing what it is designed to do, but the graph is not what you want.

    Here's a simple example.

    Code:
    webuse grunfeld, clear
    tsline invest mvalue kstock if company == 1
    Click image for larger version

Name:	tsline1.png
Views:	1
Size:	11.2 KB
ID:	1355561




    What are the solutions? They include

    1. Messing with the variables. One trick is to multiply (or equivalently to divide) some or all of the variables, so that their scaled values are then comparable. At its cleanest this is just a matter of scaling all variables relative to values in a base year. Otherwise you need to ensure that axis labels tell the truth. But many people hate this kind of graph in principle, or object on other grounds.

    2. Separate graphs for each response variable, which you then graph combine. This is quite flexible in various ways, but scaffolding gets repeated and you have to work hard at editing the combined graph to something simpler.

    3.
    sparkline from SSC. This was designed with the idea of showing several time series and so can seem over-Spartan for a few.

    Code:
    * ssc inst sparkline
    sparkline  invest mvalue kstock year if company == 1

    Click image for larger version

Name:	tsline2.png
Views:	1
Size:	12.2 KB
ID:	1355562



    4. Whatever I've forgotten about. This isn't just a joke heading for logical completeness, as some of the point of this thread is to ask what I am overlooking.

    5. It strikes me that when you have multiple time series, but they are panel or panel-like data, there is a lot of flexibility that comes with using an
    by() option. So, the main idea here, why not restructure the data temporarily, so that different variables become separate blocks of values in a combined response variable?

    Here is some token code, which is indicative rather than definitive. There is no help file and there may not ever be one, as I don't want flak for not supporting all possible graphs.
    version 11 is notional; it works with 11 and may work on some earlier versions, but you'd need to try it to see (and edit that statement).

    Code:
    *! 1.0.0 NJC 5sept2016
    program multtsline
        version 11
        syntax varlist(numeric) [if] [in] ///
        [, byopts(str asis) mylabels(str asis) *]
        
        quietly {
            marksample touse
            count if `touse'
            if r(N) == 0 exit 2000
    
            tsset
            local panelvar `r(panelvar)'            
            local timevar `r(timevar)'
        
            local varlist : list varlist - timevar
            if "`varlist'" == "" exit 102
    
            preserve
            keep if `touse'
            drop `touse'
        
            gettoken yvar varlist : varlist
            local J = 0
            while "`yvar'" != "" {
                local ++J
                local lbl`J' : var label `yvar'
                if `"`lbl`J''"' == "" local lbl`J' "`yvar'"
                local call `call' `yvar' `timevar' `panelvar'
                gettoken yvar varlist : varlist
            }
    
            tempname y
            stack `call', into(`y' `timevar' `panelvar') clear
    
            if `"`mylabels'"' != "" {
                tokenize `mylabels'
                forval j = 1/`J' {
                    label def _stack `j' `"``j''"', add
                }
            }
            else forval j = 1/`J' {
                label def _stack `j' `"`lbl`j''"', add
            }
            label val _stack _stack
        }
    
        sort `panelvar' `timevar'
    
        line `y' `timevar', by(_stack, col(1) yrescale note("") `byopts') ///
        ytitle("") xtitle("") yla(, ang(h)) c(L) ///
        subtitle(, pos(9) bcolor(none) nobexpand place(e)) `options'
    end


    Here is a default graph. We shunt the subtitles to the left to avoid breaking the view up and down. There is a default of one column of graphs. (If you want something else, you'll have to clone and edit the code.) tsset or xtset data are required.

    Code:
    multtsline invest mvalue kstock if company == 1

    Click image for larger version

Name:	tsline3.png
Views:	1
Size:	11.8 KB
ID:	1355563




    The Grunfeld data aren't a hard test. Key detail: What appears on the left are the variable labels, and if there aren't any, the variable names. In the Grunfeld data, there are no variable labels. If there were variable labels, they would usually be longer than the names. But as you can see horizontal layout is the default (and vertical would be unreadable in most cases, even for a few variables). Let's imagine some long variable labels:


    Code:
    label var invest "something longer"
    label var mvalue "would be more difficult"
    label var kstock "to show compactly"
    multtsline invest mvalue kstock if company == 1

    Click image for larger version

Name:	tsline4.png
Views:	1
Size:	12.9 KB
ID:	1355564



    You see the point. In turn you could reach for the wonderful Graph Editor to split the labels. Or if you have looked at the code above you will have seen a mylabels() option, although you need to think about what you type and understand compound double quotes:

    Code:
    multtsline invest mvalue kstock if company == 1 , mylabels(`" `" "something" "longer" "' `" "would be" "more difficult" "' `" "to show" "compactly" "' "')
    Click image for larger version

Name:	tsline5.png
Views:	1
Size:	13.0 KB
ID:	1355565



    Or you could just modify the code to be smarter automatically. That would probably double the code. Still, splitvallabels (Nick Winter, Ben Jann) from SSC would be a source of ideas.
    Last edited by Nick Cox; 05 Sep 2016, 13:42.

  • #2
    there is no command multtsline in stata, can you please explain, I also searched on google, multtsline is never discussed anywhere and google give only this page if I search multtsline in google

    Comment


    • #3
      The code for multtsline was given in the very post you’re replying to. Otherwise I could not have used it to produce graphs,

      More recently I have posted multiline on SSC.

      Comment


      • #4
        thank you so much, I think I can handle my work with help of multiline command

        Comment


        • #5
          I actually have to plot 13 different lines, and that makes y axis very small and line pattern is not visible when there are so many lines, up to 6 lines, it fairly show the pattern but more than that not, is there a way to increase graph size vertically, I have use ysize() command but that is of no use

          Comment


          • #6
            There's not a great deal of information in #5. Note that ysize() is an option, not a command.

            Are these different variables, or different groups?

            Are you using data on the same scale (i.e. with the same units of measurement)?

            Is it important to be able to identify individual series?

            Sometimes a front-and-back plot helps. https://www.statalist.org/forums/for...ailable-on-ssc
            https://stats.stackexchange.com/ques...es-in-one-plot

            Sometimes grouping into say 4, 3, 3, 3 series can help. Then you are plotting 4 panels, not 13.

            Comment


            • #7
              They are different variables.
              x axis is time and same for all, y axis variables have different scales.
              yes important to differentiate them probably through legends

              yes I am also thinking to divide them in 3 or 4 groups, I will check the link providedd by you, thanks

              Comment


              • #8
                I want to group my variables, I think I can do with graph combine command, can grouping be done with multiline command ?

                Comment


                • #9
                  No. One response, one panel is the rule.

                  Comment


                  • #10
                    for example if in the above graph, if you want invest and kstock appear on same y axis and mvalue on another y axis, what you will do to combine invest and kstock on one y axis and mvalue on another.

                    Comment


                    • #11
                      Hi Nick, thank you so much for sharing your code. I have a question that I have daily time series, the format of which is like 02Feb2019, is there any way to modify the code so that it shows years on x axis?

                      Comment


                      • #12
                        That is nothing specifically to do with my programs, but something like

                        Code:
                        xlabel(, format(%tdCY)) 
                        may help.

                        Comment


                        • #13
                          Yes that works, thank you very much!

                          Comment

                          Working...
                          X