I've seen a nice visualisation about election results that I want to reproduce with ods graphics. The original graph is attached second.
I'm getting close but there are still some things that need fixes.
The pending challenges are remarked in my sgplot output.
data wahl;
i=1;
format _2023 _2019 percent9.1 _delta 9.1 party $20.;
do party='CDU', 'AfD', 'SPD', 'Grüne', 'FDP', 'FW';
_2023=choosen(i, .345, .184, .151, .148, .05, .035);
_delta=choosen(i, 7.6, 5.3, -4.7, -5, -2.5, .5);
arrow=(_delta > 0)+1;
_2019=_2023 - _delta/100;
fake=-.5;
i+1;
dummy='all';
output;
end;
run;
data myattrmap;
set wahl(rename=(party=value));
length id $9 linecolor markersymbol textcolor $20;
fillcolor=choosec(_n_, "black", "blue", "red", "green", "yellow", "grey");
markersymbol=choosec(_n_, "star", "triangle", "starfilled", "home", "squarefilled", "hash");
textcolor=choosec(arrow, "red", "green");
id="id1";
run;
proc format;
value grp
1 = "(*ESC*){unicode '25BC'x}"
2 = "(*ESC*){unicode '25B2'x}";
run;
proc format;
picture signy
0<-high='009.9'( prefix='+');
run;
data anno_footnote1;
length function $10 anchor $20 drawspace $20;
function='text';
drawspace='GraphPercent';
x1=80; y1=3;
label= "Tendenz Vergleich zuir Wahl 2028";
textcolor='gray77'; textsize=6;
width=100;
run;
data anno_footnote2;
length function $10 anchor $20 drawspace $20;
function='text';
drawspace='GraphPercent';
x1=10; y1=1;
label="Quelle: Hessisches Statistische Landesamt";
textcolor='gray77'; textsize=6;
width=5000;
run;
data anno_footnote;
set anno_footnote1 anno_footnote2;
run;
title 'Stimmverteilung Hessen' bold justify=left;
title2 '';
title3 'Vorl. amtliches Endergebnis' ;
ods graphics on / noborder;
proc sgplot data=wahl dattrmap=myattrmap noautolegend noborder nowall sganno=anno_footnote;
ods output sgplot=sg;
format arrow grp. _delta signy.;
vbar party / response=_2023 group=party dataskin=pressed attrid=id1 barwidth=0.5 categoryorder=respdesc legendlabel='now' ;
vbar party / response=_2019 group=party dataskin=pressed attrid=id1 transparency=0.7 barwidth=0.5 discreteoffset=0.15 legendlabel='last' ;
vbar party / response=fake group=party attrid=id1 barwidth=0.85 y2axis ;
xaxistable _2023 / classdisplay=cluster VALUEATTRS=(SIZE=14 ) nolabel location=inside ;
xaxistable _delta / classdisplay=cluster VALUEATTRS=(SIZE=11 ) nolabel textgroupid=id1 textgroup=party location=inside name='txt' ;
xaxistable arrow / classdisplay=cluster VALUEATTRS=(SIZE=11 ) nolabel location=inside ;
xaxis valueattrs=(size=14 weight=bold) display=(NOLINE NOTICKS nolabel ) ;
yaxis display=none offsetmin=0.1 min=0 max=0.4;
y2axis display=none offsetmax=0.2 max=50 min=-.5;
run;
data wahl;
i=1;
format _2023 _2019 percent9.1 _delta 9.1 party $20.;
do party='CDU', 'AfD', 'SPD', 'Grüne', 'FDP', 'FW';
_2023=choosen(i, .345, .184, .151, .148, .05, .035);
_delta=choosen(i, 7.6, 5.3, -4.7, -5, -2.5, .5);
arrow=(_delta > 0)+1;
_2019=_2023 - _delta/100;
fake=-.08;
i+1;
dummy='all';
output;
end;
run;
data wahl2;
set wahl;
fake2=-0.075;
y_percent=-0.02;
green_red_y=-0.04;
green_delta=ifc(_delta>=0,cats('+',_delta),' ');
red_delta=ifc(_delta<0,cats(_delta),' ');
arrow_y_up=-0.06;
arrow_party_up=ifc(arrow=2,party,' ');
arrow_y_down=-0.06;
arrow_party_down=ifc(arrow=1,party,' ');
text_y=-0.1;
run;
title j=l "Stimmverteilung Hessen";
title2 ' ';
title3 j=l c=gray 'Vorl. amtliches Endergebnis';
footnote j=r c=gray h=0.8 'Tendenz Vergleich zuir Wahl 2028';
footnote2 j=l c=gray h=0.8 'Quelle: Hessisches Statistische Landesamt';
proc sgplot data=wahl2 noautolegend noborder;
styleattrs datacolors=("black" "blue" "red" "green" "yellow" "grey");
vbarparm category=party response=fake/group=party barwidth=0.7 dataskin=pressed nooutline displaybaseline=off transparency=0.3;
vbarparm category=party response=fake2/group=party barwidth=1 displaybaseline=off nooutline fillattrs=(color=white) ;
vbarparm category=party response=_2019/group=party dataskin=pressed displaybaseline=off nooutline displaybaseline=off
discreteoffset=0.1 barwidth=0.5 transparency=0.7;
vbarparm category=party response=_2023/group=party dataskin=pressed displaybaseline=off nooutline displaybaseline=off
discreteoffset=-0.1 barwidth=0.5 transparency=0.3 ;
scatter x=party y=y_percent /markerchar=_2023 markercharattrs=(weight=bold size=8) labelstrip;
scatter x=party y=green_red_y/markerchar=green_delta markercharattrs=(color=green size=8) labelstrip ;
scatter x=party y=green_red_y/markerchar=red_delta markercharattrs=(color=red size=8) labelstrip ;
scatter x=arrow_party_up y=arrow_y_up/markerattrs=(symbol=trianglefilled color=greyaa size=10) ;
scatter x=arrow_party_down y=arrow_y_down/markerattrs=(symbol=triangledownfilled color=greyaa size=10) ;
scatter x=party y=text_y/markerchar=party markercharattrs=(color=black weight=bold size=10) labelstrip ;
yaxis display=none ;
xaxis display=none;
run;
data wahl;
i=1;
format _2023 _2019 percent9.1 _delta 9.1 party $20.;
do party='CDU', 'AfD', 'SPD', 'Grüne', 'FDP', 'FW';
_2023=choosen(i, .345, .184, .151, .148, .05, .035);
_delta=choosen(i, 7.6, 5.3, -4.7, -5, -2.5, .5);
arrow=(_delta > 0)+1;
_2019=_2023 - _delta/100;
fake=-.08;
i+1;
dummy='all';
output;
end;
run;
data wahl2;
set wahl;
fake2=-0.075;
y_percent=-0.02;
green_red_y=-0.04;
green_delta=ifc(_delta>=0,cats('+',_delta),' ');
red_delta=ifc(_delta<0,cats(_delta),' ');
arrow_y_up=-0.06;
arrow_party_up=ifc(arrow=2,party,' ');
arrow_y_down=-0.06;
arrow_party_down=ifc(arrow=1,party,' ');
text_y=-0.1;
run;
title j=l "Stimmverteilung Hessen";
title2 ' ';
title3 j=l c=gray 'Vorl. amtliches Endergebnis';
footnote j=r c=gray h=0.8 'Tendenz Vergleich zuir Wahl 2028';
footnote2 j=l c=gray h=0.8 'Quelle: Hessisches Statistische Landesamt';
proc sgplot data=wahl2 noautolegend noborder;
styleattrs datacolors=("black" "blue" "red" "green" "yellow" "grey");
vbarparm category=party response=fake/group=party barwidth=0.7 dataskin=pressed nooutline displaybaseline=off transparency=0.3;
vbarparm category=party response=fake2/group=party barwidth=1 displaybaseline=off nooutline fillattrs=(color=white) ;
vbarparm category=party response=_2019/group=party dataskin=pressed displaybaseline=off nooutline displaybaseline=off
discreteoffset=0.1 barwidth=0.5 transparency=0.7;
vbarparm category=party response=_2023/group=party dataskin=pressed displaybaseline=off nooutline displaybaseline=off
discreteoffset=-0.1 barwidth=0.5 transparency=0.3 ;
scatter x=party y=y_percent /markerchar=_2023 markercharattrs=(weight=bold size=8) labelstrip;
scatter x=party y=green_red_y/markerchar=green_delta markercharattrs=(color=green size=8) labelstrip ;
scatter x=party y=green_red_y/markerchar=red_delta markercharattrs=(color=red size=8) labelstrip ;
scatter x=arrow_party_up y=arrow_y_up/markerattrs=(symbol=trianglefilled color=greyaa size=10) ;
scatter x=arrow_party_down y=arrow_y_down/markerattrs=(symbol=triangledownfilled color=greyaa size=10) ;
scatter x=party y=text_y/markerchar=party markercharattrs=(color=black weight=bold size=10) labelstrip ;
yaxis display=none ;
xaxis display=none;
run;
you're brilliant
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.