Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Home
- /
- Programming
- /
- Graphics
- /
- Re: Plot multiple series stacked vertically with y axes aligned

Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

🔒 This topic is **solved** and **locked**.
Need further help from the community? Please
sign in and ask a **new** question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 01-17-2020 05:15 AM
(3249 views)

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

1 ACCEPTED SOLUTION

Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;
```

15 REPLIES 15

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

SGPANEL

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

Can you give me an example of how should I use sgpanel here?

Thanks

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

@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...

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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:

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Thanks that's exactly what I needed!

However I'm getting this error for proc transpose:

ERROR: One or more ID variables are required.

ERROR: Failure during action initialization.

ERROR: The action stopped due to errors.

since the table is in CAS. In SAS 9.4 it works, but in CAS it says the id parameter is required. What's wrong?

However I'm getting this error for proc transpose:

ERROR: One or more ID variables are required.

ERROR: Failure during action initialization.

ERROR: The action stopped due to errors.

since the table is in CAS. In SAS 9.4 it works, but in CAS it says the id parameter is required. What's wrong?

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Please post the exact program which gives the error.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Thanks it works great.

I'll flag as solution the previous answer since this is a collateral issue CAS related.

Regards

I'll flag as solution the previous answer since this is a collateral issue CAS related.

Regards

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!

How to Concatenate Values

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.