Looking for a way to programmatically identify "the knee of the curve" of lines in a plot

Reply
Contributor
Posts: 22

Looking for a way to programmatically identify "the knee of the curve" of lines in a plot

I have a GPLOT that creates two lines (curves) for each of two test series. I want to be able to identify "the knee of the curve" for each curve through code rather than the usual visual approximation.

There is no real definition of "knee of the curve" but I am thinking it would be the first point in which the line between two adjacent values of the 'X' axis has a slope of 1.

I would like to have that point highlighted in some way on each line.

Any suggestions?

Trusted Advisor
Posts: 2,116

Re: Looking for a way to programmatically identify "the knee of the curve" of lines in a plot

To say that the slope is 1 means the tangent line to the curve is at a 45 degree angle.  In high school geometry terms, rise=run.  Thus

the distance between the adjacent x's is equal to the distance between the adjacent y's.  You should be able to find that point using LAG variables and a DATA step.  Once you have found it, you can create an annotate data set to label the location on the graph.

Using the ANNOTATE facility is a bit clumsy, but I think that is what you would have to do using GPLOT.  If you have a more recent version of SAS (9.3, especially), you could use SGPLOT and label or highlight sections much more easily.  If you've never used the SG plotting capability, check out the Graphically Speaking blog for lots of good examples ( Graphically Speaking - Data Visualization with a focus on SAS ODS Graphics ).

Doc Muhlbaier

Duke

Respected Advisor
Posts: 4,934

Re: Looking for a way to programmatically identify "the knee of the curve" of lines in a plot

This is the outline of how you could create that graph with SGPLOT (untested) :

proc sort data=myData; by series x; run;

data myGraph;

retain kneeFound 0;
set myData;
by series;
if first.series then kneeFound = 0;

else kneeFound = kneeFound or dif(y) >= dif(x);
nbOverKnee + kneeFound;
if nbOverKnee = 1 then  yK = Y;

run;

proc sgplot data=myGraph;
series x=x y=y / group=series;
scatter x=x y=yK / group=series;
run;

You could omit the group= option in the scatter statement if you wanted both knees to be identified with the same symbol.

PG

PG
Contributor
Posts: 22

Re: Looking for a way to programmatically identify "the knee of the curve" of lines in a plot

Just wanted to say thanks. I haven't tried this yet but it looks viable.

Respected Advisor
Posts: 4,934

Re: Looking for a way to programmatically identify "the knee of the curve" of lines in a plot

I took the time to do some testing and found some snags :smileyangry: ! So here is a better alternative:

data myData;
series = 1;
do x = 0 to 1 by 0.05;
     y = x**2;
     output;
     end;
series = 2;
do x = 0 to 1 by 0.05;
     y = x**3;
     output;
     end;
run;

proc sort data=myData; by series x; run;

data myGraph;
retain kneeFound;
length yText $20;
set myData;
by series;
aboveKnee = dif(y) > dif(x);
if first.series then kneeFound = 0;

else do;
     if not kneeFound and aboveKnee then do;
          yK = Y;
          yText = catt("x=",x," y=",y); /* In case you need a label */
          end;
     kneeFound = kneeFound or aboveKnee;

     end;
run;

proc sgplot data=myGraph;
series x=x y=y / group=series;
scatter x=x y=yK / group=series datalabel=yText;
run;

and here is the resulting graph

PGSGPlot3.png

PG
Ask a Question
Discussion stats
  • 4 replies
  • 1053 views
  • 0 likes
  • 3 in conversation