Announcement

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

  • Dual-shaded area graph around a cutoff value

    Dear Stata list,

    I am trying to produce an area plot that shades positive values as red and negative values as green for a concentration index I have constructed (flip in colours to convention to do with inequality - the values shown are the gap to line of equality in a concentration curve)
    I have gotten 95% of the way there (attached below) - but would like to join the lines to create a smooth transition from neg-pos / pos-neg, rather than have overlap around changes from negative to positive/ positive to negative (i.e., between 0.3-0.5, the line does not run onto each other)
    I have thought through this, and the first solution that comes to mind is creating points between every existing point, and coding those points to zero if the coordinates before and after are of differing signs - but I have struggled to implement this.
    I have also tried the dropline plot, which gives a better overall look - but would like to have the area shaded.
    (I have tried this too, but do not get the clean transitions I am looking for - https://www.statalist.org/forums/for...-cyclic-series)


    If you have a solution / could help in coding the transitions to ensure they line up with each other, I would be most grateful!
    I have tried separating the series into a positive and negative series, which is why there is now overlap, having coded missing values to zero. However if there is a simpler way to colour positive area (area above a value) differently to negative values (below a value) that would also be truly helpful.

    Code and data is below.

    Thanks in advance!
    Zac

    Click image for larger version

Name:	FRA_DR_CONTACTS_GAP.png
Views:	1
Size:	39.8 KB
ID:	1708700




    Data example:
    Code:
    * Example generated by -dataex-. For more info, type help dataex
    clear
    input float(DR_CONTACTS pos_DR_CONTACTS neg_DR_CONTACTS) str3 strCOUNTRY float PTILE
               0           0            0 "FRA"   0
      .004836503  .004836503            0 "FRA" .05
       .00766629   .00766629            0 "FRA"  .1
      .004911914  .004911914            0 "FRA" .15
       .00768739   .00768739            0 "FRA"  .2
      .010643587  .010643587            0 "FRA" .25
      .008195519  .008195519            0 "FRA"  .3
    -.0014103353           0 -.0014103353 "FRA" .35
     -.005840927           0  -.005840927 "FRA"  .4
    -.0035054684           0 -.0035054684 "FRA" .45
      .005300134  .005300134            0 "FRA"  .5
     .0016778708 .0016778708            0 "FRA" .55
      .001959741  .001959741            0 "FRA"  .6
      .005188048  .005188048            0 "FRA" .65
     .0039619207 .0039619207            0 "FRA"  .7
      .003540456  .003540456            0 "FRA" .75
      .003118992  .003118992            0 "FRA"  .8
      .002697468  .002697468            0 "FRA" .85
     .0022759438 .0022759438            0 "FRA"  .9
      .006375968  .006375968            0 "FRA" .95
               0           0            0 "FRA"   1
    end


    Code for graph (with some formatting/looping variables omitted)
    Code:
    graph twoway area neg_DR_CONTACTS PTILE if strCOUNTRY == "FRA", yla(-0.04(0.01)0.06) yline(0, lcolor(navy)) col(dkgreen) || area pos_DR_CONTACTS PTILE if strCOUNTRY == "FRA", color(maroon) legend(label(1 "Pro-poor") label(2 "Pro-rich")) ytitle("DR_CONTACTS_equality_gap") xtitle("Cumulative population")
    Edit: Apologies if I have missed any conventions - but have tried as much as possible to stick to them.
    Last edited by Zachary Abel; 06 Apr 2023, 03:19.

  • #2
    I've done this with ENSO data: see https://www.statalist.org/forums/for...-cyclic-series (except that I got the community convention on red and blue the wrong way round: see e.g. https://psl.noaa.gov/enso/mei/ if curious)

    The tricks I can suggest are that values you don't want to see should be missing, not zero, which carries a need to spell out cmissing(n).

    This may get you closer.

    Code:
    replace pos = . if inrange(PTILE, .399, .401)
    replace neg = . if !inrange(PTILE, .34, .46)
    
    graph twoway area neg_DR_CONTACTS PTILE if strCOUNTRY == "FRA", yla(-0.04(0.01)0.06) yline(0, lcolor(navy)) col(dkgreen) cmissing(n) || area pos_DR_CONTACTS PTILE if strCOUNTRY == "FRA", color(maroon) cmissing(n) legend(label(1 "Pro-poor") label(2 "Pro-rich")) ytitle("DR_CONTACTS_equality_gap") xtitle("Cumulative population")

    Comment


    • #3
      This can also be seen as a problem of insufficient data points in which case interpolation may help.

      Code:
      clear
      input float(DR_CONTACTS pos_DR_CONTACTS neg_DR_CONTACTS) str3 strCOUNTRY float PTILE
                 0           0            0 "FRA"   0
        .004836503  .004836503            0 "FRA" .05
         .00766629   .00766629            0 "FRA"  .1
        .004911914  .004911914            0 "FRA" .15
         .00768739   .00768739            0 "FRA"  .2
        .010643587  .010643587            0 "FRA" .25
        .008195519  .008195519            0 "FRA"  .3
      -.0014103353           0 -.0014103353 "FRA" .35
       -.005840927           0  -.005840927 "FRA"  .4
      -.0035054684           0 -.0035054684 "FRA" .45
        .005300134  .005300134            0 "FRA"  .5
       .0016778708 .0016778708            0 "FRA" .55
        .001959741  .001959741            0 "FRA"  .6
        .005188048  .005188048            0 "FRA" .65
       .0039619207 .0039619207            0 "FRA"  .7
        .003540456  .003540456            0 "FRA" .75
        .003118992  .003118992            0 "FRA"  .8
        .002697468  .002697468            0 "FRA" .85
       .0022759438 .0022759438            0 "FRA"  .9
        .006375968  .006375968            0 "FRA" .95
                 0           0            0 "FRA"   1
      end
      
      frame put *, into(graph)
      
      frame graph{
          expand 10
          bys PTILE: replace DR_CONTACTS=. if _n>1
          bys PTILE: replace PTILE= PTILE[_n-1]+0.005 if _n>1
          keep in 1/201
          ipolate DR_CONTACTS PTILE, g(new)
          replace pos_DR_CONTACTS=cond(new>0, new, 0)
          replace neg_DR_CONTACTS=cond(new<0, new, 0)
         
          set scheme s1color
          graph twoway area neg_DR_CONTACTS PTILE if strCOUNTRY ///
           == "FRA", yla(-0.04(0.01)0.06) yline(0, lcolor(navy)) col(dkgreen) ///
           cmissing(n) || area pos_DR_CONTACTS PTILE if strCOUNTRY ///
           == "FRA", color(maroon) cmissing(n) legend(label(1 "Pro-poor") ///
           label(2 "Pro-rich")) ytitle("DR_CONTACTS_equality_gap") ///
           xtitle("Cumulative population")
      }
      frame drop graph
      Click image for larger version

Name:	Graph.png
Views:	1
Size:	34.0 KB
ID:	1708739

      Comment


      • #4
        Thank you Andrew Musau and Nick Cox for your quick replies!
        Andrew - the picture is exactly what I'm after.
        I've managed to reproduce it for a single country, but had some issues reproducing in the full data-set. Nevertheless, more than enough to go on and tinker with - thanks!

        Comment


        • #5
          ipolate allows the -by- prefix, so this may be relevant to extending it to panel data. But if you struggle, just post a reproducible example with a few countries.

          Comment


          • #6
            Thanks - Andrew Musau.
            I'm struggling a bit with it - my code seems to be reproducing a wide array of points outside of the bounds of existing points, rather than interpolating properly.

            A fuller data example is below - which includes 3 countries and 2 variables (I am working with 16 countries and 8 variables in total).
            I have also included the graphing code I have been using (an example), and my attempt at creating the code for the full set...
            (Note, the graphing block has started producing an error (parenthesis don't balance) - only when including the name function for the graph - without it, the code functions perfectly)

            Once again - any help you could lend would be greatly appreciated!

            Zac


            Code:
            * Example generated by -dataex-. For more info, type help dataex
            clear
            input float(DR_CONTACTS pos_DR_CONTACTS neg_DR_CONTACTS SURG_CONTACTS pos_SURG_CONTACTS neg_SURG_CONTACTS) str3 strCOUNTRY float PTILE
                        0           0             0            0           0            0 "FRA"   0
               .004836503  .004836503             0   -.01548027           0   -.01548027 "FRA" .05
                .00766629   .00766629             0  -.020035625           0  -.020035625 "FRA"  .1
               .004911914  .004911914             0   -.01524125           0   -.01524125 "FRA" .15
                .00768739   .00768739             0  -.019822493           0  -.019822493 "FRA"  .2
               .010643587  .010643587             0   -.01993352           0   -.01993352 "FRA" .25
               .008195519  .008195519             0  -.018827617           0  -.018827617 "FRA"  .3
             -.0014103353           0  -.0014103353  -.016127706           0  -.016127706 "FRA" .35
              -.005840927           0   -.005840927  -.020095527           0  -.020095527 "FRA"  .4
             -.0035054684           0  -.0035054684  -.020881504           0  -.020881504 "FRA" .45
               .005300134  .005300134             0  -.016871631           0  -.016871631 "FRA"  .5
              .0016778708 .0016778708             0   -.01582402           0   -.01582402 "FRA" .55
               .001959741  .001959741             0   -.01200354           0   -.01200354 "FRA"  .6
               .005188048  .005188048             0   -.01213193           0   -.01213193 "FRA" .65
              .0039619207 .0039619207             0  -.008240461           0  -.008240461 "FRA"  .7
               .003540456  .003540456             0  -.006794512           0  -.006794512 "FRA" .75
               .003118992  .003118992             0  -.005348504           0  -.005348504 "FRA"  .8
               .002697468  .002697468             0 -.0039025545           0 -.0039025545 "FRA" .85
              .0022759438 .0022759438             0  -.002456665           0  -.002456665 "FRA"  .9
               .006375968  .006375968             0  .0029470325 .0029470325            0 "FRA" .95
                        0           0             0            0           0            0 "FRA"   1
                        0           0             0            0           0            0 "IND"   0
               .005672377  .005672377             0   .009077769  .009077769            0 "IND" .05
                .00852488   .00852488             0    .01020225   .01020225            0 "IND"  .1
               .005101547  .005101547             0 -.0014238358           0 -.0014238358 "IND" .15
               .005874947  .005874947             0 -.0012639165           0 -.0012639165 "IND"  .2
               .005042985  .005042985             0 -.0021862388           0 -.0021862388 "IND" .25
              .0008387566 .0008387566             0  -.009078175           0  -.009078175 "IND"  .3
               .003066778  .003066778             0  -.010277212           0  -.010277212 "IND" .35
              .0021412969 .0021412969             0  -.011861712           0  -.011861712 "IND"  .4
              -.001738161           0   -.001738161  -.015413374           0  -.015413374 "IND" .45
            -.00049084425           0 -.00049084425  -.012485564           0  -.012485564 "IND"  .5
               -.00275445           0    -.00275445  -.014018655           0  -.014018655 "IND" .55
              -.000598371           0   -.000598371 -.0087580085           0 -.0087580085 "IND"  .6
              -.004898489           0   -.004898489  -.009238303           0  -.009238303 "IND" .65
              -.007434785           0   -.007434785  -.008979559           0  -.008979559 "IND"  .7
              -.005406916           0   -.005406916  -.010689557           0  -.010689557 "IND" .75
              -.005409896           0   -.005409896   -.01086992           0   -.01086992 "IND"  .8
               -.00580734           0    -.00580734  -.011306047           0  -.011306047 "IND" .85
              -.005444288           0   -.005444288  -.008861244           0  -.008861244 "IND"  .9
             -.0030287504           0  -.0030287504  -.005106211           0  -.005106211 "IND" .95
                        0           0             0            0           0            0 "IND"   1
                        0           0             0            0           0            0 "USA"   0
               .008883119  .008883119             0   .004275959  .004275959            0 "USA" .05
                 .0106294    .0106294             0  .0011487678 .0011487678            0 "USA"  .1
                .01872808   .01872808             0   .011720926  .011720926            0 "USA" .15
                .01360163   .01360163             0   .010985613  .010985613            0 "USA"  .2
               .004762784  .004762784             0    .00524269   .00524269            0 "USA" .25
               .005724281  .005724281             0   .005020499  .005020499            0 "USA"  .3
               .012140512  .012140512             0   .010826677  .010826677            0 "USA" .35
               .006802559  .006802559             0    .01001808   .01001808            0 "USA"  .4
                .00928396   .00928396             0   .013061255  .013061255            0 "USA" .45
               .013640165  .013640165             0    .01992285   .01992285            0 "USA"  .5
                .00983709   .00983709             0   .015502632  .015502632            0 "USA" .55
               .003059983  .003059983             0   .003700733  .003700733            0 "USA"  .6
               .006262004  .006262004             0   .003363907  .003363907            0 "USA" .65
              .0017894506 .0017894506             0  -.003294349           0  -.003294349 "USA"  .7
              -.004751503           0   -.004751503   -.01129067           0   -.01129067 "USA" .75
              -.006462634           0   -.006462634 -.0035838485           0 -.0035838485 "USA"  .8
               .002994299  .002994299             0   .000870049  .000870049            0 "USA" .85
              .0038654804 .0038654804             0  .0022787452 .0022787452            0 "USA"  .9
              .0019663572 .0019663572             0   .002842128  .002842128            0 "USA" .95
                        0           0             0            0           0            0 "USA"   1
            end
            Graphing function:

            Code:
            local action DR_CONTACTS SURG_CONTACTS
            local country "FRA" "USA" "IND"
            foreach i of local action{
                foreach j of local country{
                    graph twoway area neg_`i' PTILE if strCOUNTRY == "`j'", yla(-0.04(0.01)0.06) ///
            yline(0, lcolor(navy)) col(dkgreen) || area pos_`i' PTILE if strCOUNTRY == "`j'", color(maroon) ///
            legend(label(1 "Pro-poor") label(2 "Pro-rich")) ytitle("`i'_equality_gap") ///
            ​​​​​​​xtitle("Cumulative population") name(`j'_`k')
                }
            }
            Attempt at expanding the interpolation:

            Code:
            global DEVIATION SURG_CONTACTS DR_CONTACTS
            levelsof strCOUNTRY, local(level) 
                foreach k of global DEVIATION{
                    foreach j of local level{
                            expand 10
                            bys country PTILE: replace DR_CONTACTS=. if _n>1
                            bys country PTILE: replace PTILE= PTILE[_n-1]+0.005 if _n>1
                            keep in 1/201
                            by country: ipolate DR_CONTACTS PTILE, g(new)
                            replace pos_DR_CONTACTS=cond(new>0, new, 0)
                            replace neg_DR_CONTACTS=cond(new<0, new, 0)
                        }
                    }

            Comment


            • #7
              Code:
              * Example generated by -dataex-. For more info, type help dataex
              clear
              input float(DR_CONTACTS pos_DR_CONTACTS neg_DR_CONTACTS SURG_CONTACTS pos_SURG_CONTACTS neg_SURG_CONTACTS) str3 strCOUNTRY float PTILE
                          0           0             0            0           0            0 "FRA"   0
                 .004836503  .004836503             0   -.01548027           0   -.01548027 "FRA" .05
                  .00766629   .00766629             0  -.020035625           0  -.020035625 "FRA"  .1
                 .004911914  .004911914             0   -.01524125           0   -.01524125 "FRA" .15
                  .00768739   .00768739             0  -.019822493           0  -.019822493 "FRA"  .2
                 .010643587  .010643587             0   -.01993352           0   -.01993352 "FRA" .25
                 .008195519  .008195519             0  -.018827617           0  -.018827617 "FRA"  .3
               -.0014103353           0  -.0014103353  -.016127706           0  -.016127706 "FRA" .35
                -.005840927           0   -.005840927  -.020095527           0  -.020095527 "FRA"  .4
               -.0035054684           0  -.0035054684  -.020881504           0  -.020881504 "FRA" .45
                 .005300134  .005300134             0  -.016871631           0  -.016871631 "FRA"  .5
                .0016778708 .0016778708             0   -.01582402           0   -.01582402 "FRA" .55
                 .001959741  .001959741             0   -.01200354           0   -.01200354 "FRA"  .6
                 .005188048  .005188048             0   -.01213193           0   -.01213193 "FRA" .65
                .0039619207 .0039619207             0  -.008240461           0  -.008240461 "FRA"  .7
                 .003540456  .003540456             0  -.006794512           0  -.006794512 "FRA" .75
                 .003118992  .003118992             0  -.005348504           0  -.005348504 "FRA"  .8
                 .002697468  .002697468             0 -.0039025545           0 -.0039025545 "FRA" .85
                .0022759438 .0022759438             0  -.002456665           0  -.002456665 "FRA"  .9
                 .006375968  .006375968             0  .0029470325 .0029470325            0 "FRA" .95
                          0           0             0            0           0            0 "FRA"   1
                          0           0             0            0           0            0 "IND"   0
                 .005672377  .005672377             0   .009077769  .009077769            0 "IND" .05
                  .00852488   .00852488             0    .01020225   .01020225            0 "IND"  .1
                 .005101547  .005101547             0 -.0014238358           0 -.0014238358 "IND" .15
                 .005874947  .005874947             0 -.0012639165           0 -.0012639165 "IND"  .2
                 .005042985  .005042985             0 -.0021862388           0 -.0021862388 "IND" .25
                .0008387566 .0008387566             0  -.009078175           0  -.009078175 "IND"  .3
                 .003066778  .003066778             0  -.010277212           0  -.010277212 "IND" .35
                .0021412969 .0021412969             0  -.011861712           0  -.011861712 "IND"  .4
                -.001738161           0   -.001738161  -.015413374           0  -.015413374 "IND" .45
              -.00049084425           0 -.00049084425  -.012485564           0  -.012485564 "IND"  .5
                 -.00275445           0    -.00275445  -.014018655           0  -.014018655 "IND" .55
                -.000598371           0   -.000598371 -.0087580085           0 -.0087580085 "IND"  .6
                -.004898489           0   -.004898489  -.009238303           0  -.009238303 "IND" .65
                -.007434785           0   -.007434785  -.008979559           0  -.008979559 "IND"  .7
                -.005406916           0   -.005406916  -.010689557           0  -.010689557 "IND" .75
                -.005409896           0   -.005409896   -.01086992           0   -.01086992 "IND"  .8
                 -.00580734           0    -.00580734  -.011306047           0  -.011306047 "IND" .85
                -.005444288           0   -.005444288  -.008861244           0  -.008861244 "IND"  .9
               -.0030287504           0  -.0030287504  -.005106211           0  -.005106211 "IND" .95
                          0           0             0            0           0            0 "IND"   1
                          0           0             0            0           0            0 "USA"   0
                 .008883119  .008883119             0   .004275959  .004275959            0 "USA" .05
                   .0106294    .0106294             0  .0011487678 .0011487678            0 "USA"  .1
                  .01872808   .01872808             0   .011720926  .011720926            0 "USA" .15
                  .01360163   .01360163             0   .010985613  .010985613            0 "USA"  .2
                 .004762784  .004762784             0    .00524269   .00524269            0 "USA" .25
                 .005724281  .005724281             0   .005020499  .005020499            0 "USA"  .3
                 .012140512  .012140512             0   .010826677  .010826677            0 "USA" .35
                 .006802559  .006802559             0    .01001808   .01001808            0 "USA"  .4
                  .00928396   .00928396             0   .013061255  .013061255            0 "USA" .45
                 .013640165  .013640165             0    .01992285   .01992285            0 "USA"  .5
                  .00983709   .00983709             0   .015502632  .015502632            0 "USA" .55
                 .003059983  .003059983             0   .003700733  .003700733            0 "USA"  .6
                 .006262004  .006262004             0   .003363907  .003363907            0 "USA" .65
                .0017894506 .0017894506             0  -.003294349           0  -.003294349 "USA"  .7
                -.004751503           0   -.004751503   -.01129067           0   -.01129067 "USA" .75
                -.006462634           0   -.006462634 -.0035838485           0 -.0035838485 "USA"  .8
                 .002994299  .002994299             0   .000870049  .000870049            0 "USA" .85
                .0038654804 .0038654804             0  .0022787452 .0022787452            0 "USA"  .9
                .0019663572 .0019663572             0   .002842128  .002842128            0 "USA" .95
                          0           0             0            0           0            0 "USA"   1
              end
              
              bys strCOUNTRY: assert _N==21
              expand 10 if PTILE<1
              bys strCOUNTRY PTILE: replace DR_CONTACTS=. if _n>1
              by strCOUNTRY PTILE: replace PTILE= PTILE[_n-1]+0.005 if _n>1
              by strCOUNTRY: ipolate DR_CONTACTS PTILE, g(new)
              replace pos_DR_CONTACTS=cond(new>0, new, 0)
              replace neg_DR_CONTACTS=cond(new<0, new, 0)
              
              local action DR_CONTACTS SURG_CONTACTS
              local country FRA USA IND
              foreach i of local action{
                  foreach j of local country{
                      graph twoway area neg_`i' PTILE if strCOUNTRY == "`j'", yla(-0.04(0.01)0.06) ///
              yline(0, lcolor(navy)) col(dkgreen) || area pos_`i' PTILE if strCOUNTRY == "`j'", color(maroon) ///
              legend(label(1 "Pro-poor") label(2 "Pro-rich")) ytitle("`i'_equality_gap") ///
              xtitle("Cumulative population") name(`j'_`k')
                  }
              }

              Comment


              • #8
                Thank you, Andrew! That worked amazingly. Very much appreciate your time!

                Comment

                Working...
                X