Announcement

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

  • Combination Chart of Stacked Bar and Line Graph

    Hello all,

    I have information on a number of invoices and their payment dates. I am looking to create a combination chart, a stacked bar chart showing the percentage of invoices paid early vs late & another axis for the line graph to show the total number of invoices (observations) per year. The invoices are paid late if dayslate > 0.

    clear
    input int(Net_due_date Paymentdate dayslate) float year
    15091 15244 153 2001
    15274 15285 11 2001
    15005 15245 240 2001
    15012 15013 1 2001
    14992 15001 9 2001
    15323 15354 31 2001
    15197 15217 20 2001
    15266 15273 7 2001
    15246 15246 0 2001
    14987 14992 5 2001
    15168 15188 20 2001
    15012 15013 1 2001
    15614 15631 17 2002
    15690 15733 43 2002
    15687 15733 46 2002
    15614 15632 18 2002
    15680 15678 -2 2002
    15480 15827 347 2002
    15450 15445 -5 2002
    15650 15704 54 2002
    end

    Let me know if there is a way for me to do this or if you need anymore information.

    Kind regards,
    Kayleigh


  • #2
    You can do this, but fooling around with two scales is tricky and many people think it is a bad idea.

    See e.g. Howard Wainer:

    Wainer, H. 1991. Double Y-axis graphs. Chance 4(1): 50-51

    The result is not exciting with your data example, but I recommend e.g. multiline from SSC.

    https://www.statalist.org/forums/for...ailable-on-ssc

    Code:
    clear
    input int(Net_due_date Paymentdate dayslate) float year
    15091 15244 153 2001
    15274 15285 11 2001
    15005 15245 240 2001
    15012 15013 1 2001
    14992 15001 9 2001
    15323 15354 31 2001
    15197 15217 20 2001
    15266 15273 7 2001
    15246 15246 0 2001
    14987 14992 5 2001
    15168 15188 20 2001
    15012 15013 1 2001
    15614 15631 17 2002
    15690 15733 43 2002
    15687 15733 46 2002
    15614 15632 18 2002
    15680 15678 -2 2002
    15480 15827 347 2002
    15450 15445 -5 2002
    15650 15704 54 2002
    end
    
    bysort year : gen total = _N 
    by year: egen pclate = mean(100 * (dayslate > 0))
    
    su year, meanonly 
    multiline total pclate year, xla(`r(min)'/`r(max)')
    Last edited by Nick Cox; 07 Apr 2022, 06:29.

    Comment


    • #3
      I agree with Nick that multiple axes can be confusing, but here is a way. You will need to adjust the axes scales with more data. (Nb. Axis should read "Late/ Unpaid invoices" ).

      Code:
      clear
      input int(Net_due_date Paymentdate dayslate) float year
      15091 15244 153 2001
      15274 15285 11 2001
      15005 15245 240 2001
      15012 15013 1 2001
      14992 15001 9 2001
      15323 15354 31 2001
      15197 15217 20 2001
      15266 15273 7 2001
      15246 15246 0 2001
      14987 14992 5 2001
      15168 15188 20 2001
      15012 15013 1 2001
      15614 15631 17 2002
      15690 15733 43 2002
      15687 15733 46 2002
      15614 15632 18 2002
      15680 15678 -2 2002
      15480 15827 347 2002
      15450 15445 -5 2002
      15650 15704 54 2002
      end
      
      gen late= (dayslate >0)*100
      bys year: egen count= mean(late)
      contract year count
      set scheme s1color
      twoway (bar count year , xlabel(2001/2002, angle(0) notick) ///
      xtitle("") ysc(r(0 100) ) ylab(0(10)100) ytitle("Paid invoices (%)") ///
      xsc(r(2001 2002))  barw(0.9) bcolor(black%40) xscale(axis(1))) ///
      (scatter _freq year, connect(line) lc(blue) lwidth(medthick) ///
      mc(none) yaxis(2) ylab(0(3)15, axis(2) labcolor(blue))  ///
      ytitle(, color(blue) axis(2)) ysc(r(0 15) axis(2)) leg(off))
      Res.:
      Click image for larger version

Name:	Graph.png
Views:	1
Size:	35.3 KB
ID:	1658398

      Last edited by Andrew Musau; 07 Apr 2022, 06:07.

      Comment


      • #4
        Hi Andrew & Nick,

        Thank you so much for the very quick responses. I almost have the information I am looking for, however I would like to remove the line after the year 2021, as well as change the second y title (currently frequency). Could you help me adjust the code so it is a bit cleaned up? Also just confirming, does the line chart in this case show total number of observations, or only those that are late?

        Adjusted code:

        twoway (bar count year , xlabel(2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021, angle(90) notick) ///
        xtitle("% Paid late per year") ysc(r(0 100) ) ylab(0(10)100) ytitle("Paid invoices (%)") ///
        xsc(r(2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021)) barw(0.9) bcolor(black%40) xscale(axis(1))) ///
        (scatter _freq year, connect(line) lc(blue) lwidth(medthick) ///
        mc(none) yaxis(2) ytitle("# Invoices") ylab(0(5000)20000, axis(2) labcolor(blue)) ///
        ytitle(, color(blue) axis(2)) ysc(r(0 15) axis(2)) leg(off))

        See attachment.

        Kind regards,
        Kayleigh
        Attached Files

        Comment


        • #5
          You should upload pictures in .png format, as recommended in the FAQs. I am not able to open the graph as it is created in version 17 and I am using version 16. However, I simulate data below and modify the code.

          Originally posted by Kayleigh Amber View Post
          Also just confirming, does the line chart in this case show total number of observations, or only those that are late?
          It is the total number of invoices, late or otherwise. You should check that "dayslate" is never missing, otherwise the code below drops missing values if they exist.

          Code:
          clear
          set obs 200000
          set seed 04072022
          gen year= runiformint(2001, 2022)
          gen dayslate1 = runiformint(-100, 50) if year<2005
          gen dayslate2 = runiformint(-50, 150) if inrange(year,2005, 2010)
          gen dayslate3= runiformint(-25, 300) if inrange(year, 2011, 2015)
          gen dayslate4= runiformint(-10, 365) if inrange(year, 2016, 2022)
          egen dayslate= rowmax(dayslate?)
          drop dayslate?
          local i 1
          forval year= 2001/2022{
              bys year: drop if year==`year' & _n>`i'000
              local ++i
          }
          *START HERE
          drop if missing(dayslate)
          gen late= (dayslate >0)*100
          bys year: egen count= mean(late)
          contract year count 
          set scheme s1color
          twoway (bar count year if year<=2021 , xlabel(2001/2021, angle(90) notick) ///
           ysc(r(0 100) ) ylab(0(10)100) ytitle("% Paid late per year") ///
          xsc(r(2001/2021)) barw(0.9) bcolor(black%40) xscale(axis(1))) ///
          (scatter _freq year if year<=2021, connect(line) lc(blue) lwidth(medthick) ///
          mc(none) yaxis(2) ylab(0(5000)15000, axis(2) labcolor(blue)) ///
          ytitle("# Invoices", color(blue) axis(2)) ysc(r(0 15) axis(2)) xtitle("") leg(off))
          Click image for larger version

Name:	Graph.png
Views:	1
Size:	57.0 KB
ID:	1658451

          Comment


          • #6
            Perfect, Thank you Andrew, I will keep the png format in mind for next time!

            Comment

            Working...
            X