I have a dataset like: timestamp | VAR1 | VAR2 | VAR3.
I'd like to plot three series (timestamp,VAR1), (timestamp, VAR2), (timestamp, VAR3) in three graphs stacked vertically, so that the y axes, which may have different scales and unit of measures, should be aligned on a vertical line.
The purpose is that if I want to see what happens at a specific timestamp, I just look at the three series "vertically" on an imaginary vertical line.
So far I did three sequentially sgplots, but since the y axes values may occupy different spaces (e.g. the size of "1" "2" "3" is smaller than "1000" "2000 "3000"), the three graphs are not vertically aligned.
How can I achieve that?
I hope I made myself clear.
Thanks
Regards
I understand now. No, I do not know how to do that when you create individual graphs. The correct way to do it is to transpose the data and use SGPANEL
proc transpose
data=Have
out=Want(drop=_LABEL_ rename=(Col1=Value)) /* 2 */
name=Variable; /* 3 */
by timestamp; /* original X var */
var A B C; /* original Y vars */
run;
ods graphics / reset;
/* plot on a single scale in multiple graphs */
proc sgpanel data=Want;
panelby Variable / UNISCALE=COLUMN columns=1;
series x=timestamp y=Value;
run;
@Edoedoedo wrote:
Thanks I taught about it, however I couldn't figure out how to use it in this case, there is no groups to use in panelby and I don't want to restructure the dataset if not absolutely necessary.
Can you give me an example of how should I use sgpanel here?
Thanks
Sure, can you please provide sample data?
Here are instructions on how to provide sample data as a data step:
https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-dat...
Sure, since the dataset is very simple I assumed it could be discussed just knowing the dataset metadata!
Here's the dataset and my code so far:
data HAVE;
format timestamp datetime25.;
timestamp=datetime(); A=1; B=500000; C=0.03; output;
timestamp=datetime()+60; A=2; B=100000; C=0.05; output;
timestamp=datetime()+120; A=3; B=300000; C=0.01; output;
timestamp=datetime()+180; A=4; B=400000; C=0.02; output;
timestamp=datetime()+240; A=5; B=200000; C=0.04; output;
run;
proc sgplot data=have;
series x=timestamp y=A;
run;
proc sgplot data=have;
series x=timestamp y=B;
run;
proc sgplot data=have;
series x=timestamp y=C;
run;
As you can see the three graphs are not vertically aligned on y axes.
Moreover, I'd prefer not to create an ad-hoc temporary table, since it would require more time (in real data rows are millions and columns A B C are some dozens).
Thanks
It sounds like you want to plot all graphs on the same scale? For example, the Y axis should be [0, 50000] for all graphs?
As Reeza says, SGPANEL makes this easy if you convert form "Wide" data to "Long" data.
However, if you do not want to convert, you can either put all graphs in a single graph or you can use the YAXIS statement to set the Y axis to be the same for individual graphs:
/* plot on a single scale in one graph */
proc sgplot data=have;
series x=timestamp y=A;
series x=timestamp y=B;
series x=timestamp y=C;
run;
/* plot on a single scale in multiple graphs */
%let minY = 0;
%let maxY = 500000;
proc sgplot data=have;
series x=timestamp y=A;
yaxis min=&minY max=&maxY;
run;
proc sgplot data=have;
series x=timestamp y=B;
yaxis min=&minY max=&maxY;
run;
proc sgplot data=have;
series x=timestamp y=C;
yaxis min=&minY max=&maxY;
run;
No, I don't want to use the same scale for all graphs, every one should have its own scale. But if I look at the y axes vertically, they should be aligned.
Let me attach an image to explain what I mean:
Sorry to keep asking questions, but do you mean that you want the X axis aligned? In your example, it looks like you want to ensure that the range of the X axis is always consistent for all of the plots. In that case, you should use
/* get min and max of X */
proc sql;
select min(timestamp), max(timestamp)
into :minX, :maxX
from Have;
run;
/* plot on a single scale in multiple graphs */
proc sgplot data=have;
series x=timestamp y=A;
xaxis min=&minX max=&maxX;
run;
proc sgplot data=have;
series x=timestamp y=B;
xaxis min=&minX max=&maxX;
run;
proc sgplot data=have;
series x=timestamp y=C;
xaxis min=&minX max=&maxX;
run;
Maybe it's clear in my head but I'm not succeeding in explain it 😄
However no, in my example the x axis values are exactly the same for all three graphs, so setting min and max wouldn't change anything since the min and the max are already reached by all three graphs.
What I mean is that since the three vars have different scale (and that's ok), when the sgplot draws the y axis, it is drawn "more to the right" depending on what it has to plot on the left of the y axis, that is the numbers of the scale.
In the first graph, the numbers on the left are "1" "2" "3",... assume they occupy 10px, then there is a white space, assume it occupies 5px, and then the y axis: so it begins in the paper at coordinate 15px.
In the second graph, the numbers in the left are "100000" "200000" etc, so they occupy MORE space, assume 10px * 6 digits = 60px, then there is a white space, assume it occupies 5px as before, and then the y axis: so it begins in the paper at coordinate 65px.
Hence the two y axes are not aligned vertically! One is at 15px, one is at 65px.
My question is how to "center" the graphs so that the y axes are exactly at the same distance in pixel from the left of the paper.
I understand now. No, I do not know how to do that when you create individual graphs. The correct way to do it is to transpose the data and use SGPANEL
proc transpose
data=Have
out=Want(drop=_LABEL_ rename=(Col1=Value)) /* 2 */
name=Variable; /* 3 */
by timestamp; /* original X var */
var A B C; /* original Y vars */
run;
ods graphics / reset;
/* plot on a single scale in multiple graphs */
proc sgpanel data=Want;
panelby Variable / UNISCALE=COLUMN columns=1;
series x=timestamp y=Value;
run;
Same as the previous, but with a CAS library (instead of work):
cas session;
libname CASUSER cas caslib="CASUSER";
data CASUSER.HAVE;
format timestamp datetime25.;
timestamp=datetime(); A=1; B=500000; C=0.03; output;
timestamp=datetime()+60; A=2; B=100000; C=0.05; output;
timestamp=datetime()+120; A=3; B=300000; C=0.01; output;
timestamp=datetime()+180; A=4; B=400000; C=0.02; output;
timestamp=datetime()+240; A=5; B=200000; C=0.04; output;
run;
proc transpose
data=CASUSER.Have
out=CASUSER.Want
name=Variable;
by timestamp;
var A B C;
run;
ods graphics / reset;
/* plot on a single scale in multiple graphs */
proc sgpanel data=CASUSER.Want;
panelby Variable / UNISCALE=COLUMN columns=1;
series x=timestamp y=Col1;
run;
ERROR: One or more ID variables are required.
ERROR: Failure during action initialization.
ERROR: The action stopped due to errors.
NOTE: The Cloud Analytic Services server processed the request in 0.046021 seconds.
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE TRANSPOSE ha utilizzato (tempo totale di elaborazione):
real time 0.15 seconds
cpu time 0.05 seconds
You can add a unique identifier to each observation and use that as the ID variable:
data casuser.HAVE;
format timestamp datetime25.;
ID = _N_; timestamp=datetime(); A=1; B=500000; C=0.03; output;
ID = _N_; timestamp=datetime()+60; A=2; B=100000; C=0.05; output;
ID = _N_; timestamp=datetime()+120; A=3; B=300000; C=0.01; output;
ID = _N_; timestamp=datetime()+180; A=4; B=400000; C=0.02; output;
ID = _N_; timestamp=datetime()+240; A=5; B=200000; C=0.04; output;
run;
proc transpose
data=CASUSER.Have
out=CASUSER.Want
name=Variable;
by timestamp;
id ID;
var A B C;
run;
proc contents short data=casuser.want;
run;
/* plot on a single scale in multiple graphs */
proc sgpanel data=casuser.Want(rename=(_1=Value));
panelby Variable / UNISCALE=COLUMN columns=1;
series x=timestamp y=Value;
run;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.