Hi all
Here is some data from a Wikipedia page:
data polls;
input Date $15. @16 Polling_Organisation $21. @38 For F_LCL F_UCL Against A_LCL A_UCL Predicted_Outcome $ 9.;
datalines;
2–17 Jul 2018 Curia Market Research 49.0 47.4 50.6 -47.0 -45.5 -48.5 Undecided
15–19 Oct 2018 1 News Colmar Brunton 46.0 44.6 47.4 -41.0 -39.7 -42.3 For
10–26 Oct 2018 Horizon Research 60.0 58.1 61.9 -24.0 -23.3 -24.7 For
3–17 Mar 2019 Research New Zealand 29.0 28.2 29.8 -49.0 -47.6 -50.4 Against
9 May 2019 Horizon Research 52.0 50.5 53.5 -37.0 -35.9 -38.1 For
4–8 Jun 2019 1 News Colmar Brunton 39.0 37.8 40.2 -52.0 -50.4 -53.6 Against
3–4 Aug 2019 Horizon Research 39.0 37.8 40.2 -47.0 -45.5 -48.5 Against
11–17 Nov 2019 Horizon Research 48.0 46.6 49.4 -38.0 -36.9 -39.1 For
23–27 Nov 2019 1 News Colmar Brunton 43.0 41.7 44.3 -49.0 -47.5 -50.5 Against
8–12 Feb 2020 1 News Colmar Brunton 39.0 37.8 40.2 -51.0 -49.4 -52.6 Against
21–26 Feb 2020 Horizon Research 54.0 52.8 55.2 -45.0 -44.0 -46.0 For
6–9 Mar 2020 Research New Zealand 43.0 41.7 44.3 -33.0 -32.0 -34.0 For
10–14 Jun 2020 Horizon Research 56.0 54.6 57.4 -43.0 -41.9 -44.1 For
20–24 Jun 2020 1 News Colmar Brunton 40.0 38.8 41.2 -49.0 -47.5 -50.5 Against
9–13 Jul 2020 Research New Zealand 43.0 41.7 44.3 -39.0 -37.8 -40.2 For
20–23 Aug 2020 Research New Zealand 39.0 37.8 40.2 -46.0 -44.6 -47.4 Against
20–25 Aug 2020 Horizon Research 50.0 . . -50.0 . . Undecided
;
run;
This is the attribute map:
DATA _AttrMap;
LENGTH value $ 9 FillPattern $ 2 lineColor $ 5;
INPUT ID $ Value $ FillPattern $ lineColor $;
DATALINES;
hbar Against L1 black
hbar For R1 black
hbar Undecided X1 black
;
RUN;
And finally, this is how I plot it (please excuse the caps):
ODS GRAPHICS /WIDTH=1000 HEIGHT=600 MAXLEGENDAREA=100
IMAGENAME="Polls"
attrpriority=none;
PROC SGPLOT
NOBORDER
NOCYCLEATTRS
DATA=polls
DATTRMAP=_AttrMap
;
/* Put Polling_Organisation in the Yaxistable */
YAXISTABLE Polling_Organisation
/LOCATION=INSIDE
POSITION=LEFT
;
XAXIS LABEL="Percentage For/Against (Undecided not shown)" VALUES=(-100 TO 100 BY 10);
HBARPARM
CATEGORY=Date
RESPONSE=For
/NOFILL FILLPATTERN
GROUP=Predicted_Outcome
GROUPDISPLAY=CLUSTER ATTRID=hbar
GROUPORDER=DATA
LIMITLOWER=F_LCL
LIMITUPPER=F_UCL
LIMITATTRS=(COLOR=Black)
NAME="Leg"
;
HBARPARM
CATEGORY=Date
RESPONSE=Against
/NOFILL FILLPATTERN
GROUP=Predicted_Outcome
GROUPDISPLAY=CLUSTER ATTRID=hbar
GROUPORDER=DATA
LIMITLOWER=A_LCL
LIMITUPPER=A_UCL
LIMITATTRS=(COLOR=Black)
;
KEYLEGEND "Leg" /TITLE="Poll outcome";
REFLINE -50 50 /AXIS=X LINEATTRS=(PATTERN=ShortDash);
RUN;
Everything works, except that the legend is not mapping the correct pattern to the correct group value (see below).
What am I missing?
thanks
I do not believe controlling the sgplot hbarparm fillpattern with dattrmap is supported yet. (If you have seen documentation indicating that it is supported, let me know and I'll check more into it.) The patterns you were seeing were just the default ones (which happened to almost correspond to the ones you were specifying, but in the wrong order).
Since that technique is not supported, you'll have to use a more indirect/hard-coded/order-dependent technique, such as using a styleattrs statement:
styleattrs datafillpatterns=(X1 R1 L1);
Here's a modified version of your code, using styleattrs to control the patterns. I've also changed your dattrmap colors to make it easier to see if they're affecting the graph:
data polls;
length Date $16 Polling_Organisation $50 Predicted_Outcome $9;
infile datalines dlm=':';
input Date Polling_Organisation For F_LCL F_UCL Against A_LCL A_UCL Predicted_Outcome;
datalines;
2-17 Jul 2018 :Curia Market Research :49.0:47.4:50.6:-47.0:-45.5:-48.5:Undecided
15-19 Oct 2018 :1 News Colmar Brunton :46.0:44.6:47.4:-41.0:-39.7:-42.3:For
10-26 Oct 2018 :Horizon Research :60.0:58.1:61.9:-24.0:-23.3:-24.7:For
3-17 Mar 2019 :Research New Zealand :29.0:28.2:29.8:-49.0:-47.6:-50.4:Against
9 May 2019 :Horizon Research :52.0:50.5:53.5:-37.0:-35.9:-38.1:For
4-8 Jun 2019 :1 News Colmar Brunton :39.0:37.8:40.2:-52.0:-50.4:-53.6:Against
3-4 Aug 2019 :Horizon Research :39.0:37.8:40.2:-47.0:-45.5:-48.5:Against
11-17 Nov 2019 :Horizon Research :48.0:46.6:49.4:-38.0:-36.9:-39.1:For
23-27 Nov 2019 :1 News Colmar Brunton :43.0:41.7:44.3:-49.0:-47.5:-50.5:Against
8-12 Feb 2020 :1 News Colmar Brunton :39.0:37.8:40.2:-51.0:-49.4:-52.6:Against
21-26 Feb 2020 :Horizon Research :54.0:52.8:55.2:-45.0:-44.0:-46.0:For
6-9 Mar 2020 :Research New Zealand :43.0:41.7:44.3:-33.0:-32.0:-34.0:For
10-14 Jun 2020 :Horizon Research :56.0:54.6:57.4:-43.0:-41.9:-44.1:For
20-24 Jun 2020 :1 News Colmar Brunton :40.0:38.8:41.2:-49.0:-47.5:-50.5:Against
9-13 Jul 2020 :Research New Zealand :43.0:41.7:44.3:-39.0:-37.8:-40.2:For
20-23 Aug 2020 :Research New Zealand :39.0:37.8:40.2:-46.0:-44.6:-47.4:Against
20-25 Aug 2020 :Horizon Research :50.0:.:.:-50.0:.:.:Undecided
;
run;
DATA _AttrMap;
LENGTH value $ 9 FillPattern $ 2 lineColor $ 5;
INPUT ID $ Value $ lineColor $;
DATALINES;
hbar Against red
hbar For green
hbar Undecided gray
;
RUN;
ODS GRAPHICS /WIDTH=1000 HEIGHT=600 MAXLEGENDAREA=100 imagemap
IMAGENAME="Polls"
attrpriority=none;
title "Sgplot";
PROC SGPLOT
NOBORDER
NOCYCLEATTRS
DATA=polls
DATTRMAP=_AttrMap
;
/* Put Polling_Organisation in the Yaxistable */
YAXISTABLE Polling_Organisation
/LOCATION=INSIDE
POSITION=LEFT
;
XAXIS LABEL="Percentage For/Against (Undecided not shown)" VALUES=(-100 TO 100 BY 10);
styleattrs datafillpatterns=(X1 R1 L1);
HBARPARM
CATEGORY=Date
RESPONSE=For
/ NOFILL FILLPATTERN
GROUP=Predicted_Outcome
GROUPDISPLAY=CLUSTER ATTRID=hbar
GROUPORDER=DATA
LIMITLOWER=F_LCL
LIMITUPPER=F_UCL
LIMITATTRS=(COLOR=Black)
NAME="Leg"
;
HBARPARM
CATEGORY=Date
RESPONSE=Against
/NOFILL FILLPATTERN
GROUP=Predicted_Outcome
GROUPDISPLAY=CLUSTER ATTRID=hbar
GROUPORDER=DATA
LIMITLOWER=A_LCL
LIMITUPPER=A_UCL
LIMITATTRS=(COLOR=Black)
;
KEYLEGEND "Leg" /TITLE="Poll outcome";
REFLINE -50 50 /AXIS=X LINEATTRS=(PATTERN=ShortDash);
RUN;
Have you printed your data sets to ensure that you have the values that you think you have?
I do not believe controlling the sgplot hbarparm fillpattern with dattrmap is supported yet. (If you have seen documentation indicating that it is supported, let me know and I'll check more into it.) The patterns you were seeing were just the default ones (which happened to almost correspond to the ones you were specifying, but in the wrong order).
Since that technique is not supported, you'll have to use a more indirect/hard-coded/order-dependent technique, such as using a styleattrs statement:
styleattrs datafillpatterns=(X1 R1 L1);
Here's a modified version of your code, using styleattrs to control the patterns. I've also changed your dattrmap colors to make it easier to see if they're affecting the graph:
data polls;
length Date $16 Polling_Organisation $50 Predicted_Outcome $9;
infile datalines dlm=':';
input Date Polling_Organisation For F_LCL F_UCL Against A_LCL A_UCL Predicted_Outcome;
datalines;
2-17 Jul 2018 :Curia Market Research :49.0:47.4:50.6:-47.0:-45.5:-48.5:Undecided
15-19 Oct 2018 :1 News Colmar Brunton :46.0:44.6:47.4:-41.0:-39.7:-42.3:For
10-26 Oct 2018 :Horizon Research :60.0:58.1:61.9:-24.0:-23.3:-24.7:For
3-17 Mar 2019 :Research New Zealand :29.0:28.2:29.8:-49.0:-47.6:-50.4:Against
9 May 2019 :Horizon Research :52.0:50.5:53.5:-37.0:-35.9:-38.1:For
4-8 Jun 2019 :1 News Colmar Brunton :39.0:37.8:40.2:-52.0:-50.4:-53.6:Against
3-4 Aug 2019 :Horizon Research :39.0:37.8:40.2:-47.0:-45.5:-48.5:Against
11-17 Nov 2019 :Horizon Research :48.0:46.6:49.4:-38.0:-36.9:-39.1:For
23-27 Nov 2019 :1 News Colmar Brunton :43.0:41.7:44.3:-49.0:-47.5:-50.5:Against
8-12 Feb 2020 :1 News Colmar Brunton :39.0:37.8:40.2:-51.0:-49.4:-52.6:Against
21-26 Feb 2020 :Horizon Research :54.0:52.8:55.2:-45.0:-44.0:-46.0:For
6-9 Mar 2020 :Research New Zealand :43.0:41.7:44.3:-33.0:-32.0:-34.0:For
10-14 Jun 2020 :Horizon Research :56.0:54.6:57.4:-43.0:-41.9:-44.1:For
20-24 Jun 2020 :1 News Colmar Brunton :40.0:38.8:41.2:-49.0:-47.5:-50.5:Against
9-13 Jul 2020 :Research New Zealand :43.0:41.7:44.3:-39.0:-37.8:-40.2:For
20-23 Aug 2020 :Research New Zealand :39.0:37.8:40.2:-46.0:-44.6:-47.4:Against
20-25 Aug 2020 :Horizon Research :50.0:.:.:-50.0:.:.:Undecided
;
run;
DATA _AttrMap;
LENGTH value $ 9 FillPattern $ 2 lineColor $ 5;
INPUT ID $ Value $ lineColor $;
DATALINES;
hbar Against red
hbar For green
hbar Undecided gray
;
RUN;
ODS GRAPHICS /WIDTH=1000 HEIGHT=600 MAXLEGENDAREA=100 imagemap
IMAGENAME="Polls"
attrpriority=none;
title "Sgplot";
PROC SGPLOT
NOBORDER
NOCYCLEATTRS
DATA=polls
DATTRMAP=_AttrMap
;
/* Put Polling_Organisation in the Yaxistable */
YAXISTABLE Polling_Organisation
/LOCATION=INSIDE
POSITION=LEFT
;
XAXIS LABEL="Percentage For/Against (Undecided not shown)" VALUES=(-100 TO 100 BY 10);
styleattrs datafillpatterns=(X1 R1 L1);
HBARPARM
CATEGORY=Date
RESPONSE=For
/ NOFILL FILLPATTERN
GROUP=Predicted_Outcome
GROUPDISPLAY=CLUSTER ATTRID=hbar
GROUPORDER=DATA
LIMITLOWER=F_LCL
LIMITUPPER=F_UCL
LIMITATTRS=(COLOR=Black)
NAME="Leg"
;
HBARPARM
CATEGORY=Date
RESPONSE=Against
/NOFILL FILLPATTERN
GROUP=Predicted_Outcome
GROUPDISPLAY=CLUSTER ATTRID=hbar
GROUPORDER=DATA
LIMITLOWER=A_LCL
LIMITUPPER=A_UCL
LIMITATTRS=(COLOR=Black)
;
KEYLEGEND "Leg" /TITLE="Poll outcome";
REFLINE -50 50 /AXIS=X LINEATTRS=(PATTERN=ShortDash);
RUN;
Thanks @GraphGuy
When no one answered, I tried reaching out to SAS tech support, and they did confirm what you stated above: This is not supported as yet, which is a pity.
They pointed me to a proc template example(https://support.sas.com/kb/45/663.html), which I was able to use to get the desired outcome:
proc template;
define style mypatterns;
parent=styles.listing;
/* The GraphBar element must be included with the
FILLPATTERN option in order to use fill patterns. */
style GraphBar from GraphComponent /
displayopts = "fillpattern";
/* Fill patterns are defined using the FILLPATTERN
style element attribute.
COLOR is used for the bar fill colors
CONTRASTCOLOR is used for the line colors */
style GraphData1 from GraphData1 /
FillPattern = "X1"
ContrastColor=black
;
style GraphData2 from GraphData2 /
FillPattern = "R1"
ContrastColor=black
;
style GraphData3 from GraphData3 /
FillPattern = "L1"
ContrastColor=black
;
end;
run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.