用SAS实现堆积式南丁格尔玫瑰图Nightingale Rose Diagram (上)

ExcelPro的图表博客的作者刘老师最近用EXCEL做出了一个非常炫的图叫堆积式南丁格尔玫瑰图,还叫半径不等的扇形图、极区图 南丁格尔玫瑰图、风玫瑰图等等,据说最早是一个叫南丁格尔的护士最早使用的,她自己叫这个图为“鸡冠花图(coxcomb)”,一种圆形的直方图,除了讲述用EXCEL的具体做法,还对此图从专业方面给出了评价,指出了该图的优缺点和适用场合。具体介绍见刘老师的博文一博文二

 

这种图在excel里面是雷达图拼凑起来的,具体说是360个,当然越多图越圆,我没有试过。下面我给出用SAS代码实现的一种方法,虽然还没完成,但是大概差不多了,从构思到半成型花了差不多一天的时间,思路花了三分之一的时间,大部分时间在调试代码(好久没用,不熟练。)

下面给出我的思路:

全部用annotate完成:1,首先用PIE函数画出整个轮廓,包括外面的光圈,pie图和中心的圆;2,然后用piexy函数对各片pie进行标注;3,最后对每个pie的不同部分用point和draw函数进行标注,这里只完成了前两步,后面一步在(下)里面完成,技巧已经在包含前两步里面。

着手编程时,参考了Robslink的代码,当然,代码需要改动很大,并且原图的配色确实很逊,和上面的图没法比。



本图代码见底下附。

点评:

1,对于这样的大型图,excelpro认为用excel做的是难度是5星,实用性为3星,我认为酷劲也该给个五星。

2,excel需要构造一堆数来完成这个图形, SAS也需要一堆代码来搭积木。excel的优点就是实时可见,随时调整,而SAS则需要修改好代码后,反复运行调试参数;不过SAS还有个优点,就是一旦完成,自动化程度高。比如说下次碰到的指标为10个,比这次少一个,怎么办?excel的话,需要重新构造10块饼的数据,从头再来,而SAS就不需要,直接运行即可,因为里面用到宏直接传递这些绘图信息。     当然excel里面也有VBA,也可以自动化的功能,当然这个工作量就剧增了。

问题:

1,圆心的填色“facebook”处好呆板,SAS里面好像没有现成的那种颜色,需要用修改GTL的方法得到那种渲染效果的颜色,不过没有尝试。

2,几次遇到SAS绘图的清晰度问题,也就是怎么要得到高dpi的图,尝试了几种方法,都没有得到想要的。怎么保持图片大小不变,而清晰度增加,换个角度怎么让SAS出图片尺寸小,文件非常大,上M都可以,如果谁知道请告知,谢谢!

附代码:
%let name=rose2;
FILENAME file "c:\";

data ex;
input index $4. value col $;
col="CX"||col;
cards;
a 30 989898
a 70 353535
b 41 808080
b 59 353535
c 88 636466
c 12 353537
d 54 385599
d 46 2E4A7A
e 13 375299
e 34 2D4978
e 30 637798
e 12 8395BB
e 7 BACAE2
e 4 8F9CA8
f 11 375299
f 29 2D4978
f 23 637798
f 18 8395BB
f 12 BACAE2
f 7 8F9CA8
g 21 375299
g 28 2D4978
g 22 637798
g 29 8395BB
h 70 F1F1F1
h 30 353533
i 12 E6E6E6
i 88 353535
j 51 CCCCCC
j 49 353535
k 40 B3B3B3
k 60 353535
;
run;

/*构造控制绘图参数 PIE函数的半径rad,起始角和角度ang */
data ex2;
set ex nobs=max;
by index;
retain rad ang 0;
if first.index then
do ; rad=1;ang+1; output; end;
else do; rad+1;output; end;
if _N_=max then do; call symput("piece", ang); end;
%put &piece.;
run;

/*设置最大饼环的半径为整个图的百分比*/
%let radius=25;

data pies; set ex2;
by index;
length style function color $ 12;
xsys='3'; ysys='3'; hsys='3';
x=50; y=50; /* 定位圆心 */
function = 'PIE';
style = 'SOLID';
if first.index then do sizev = value; end;
else do ; sizev + value; end;
size=(&radius.*((sizev+40)/100)); /*最大半径为 &radius% */

angle = 10;
angle =angle + ((ang-1) / &piece.)*360;
rotate = (1/ &piece.)*360;
/*angle+((1/&piece.)*360); start angle for this slice */
/*if first=1 then angle=0; */

color=col;
output;
run;
proc sort data=pies out=pies;
by index decending sizev;
run;

/* 中心空白圆 */
data hole1; set ex2;
length style function color $ 12;
xsys='3'; ysys='3'; hsys='3';
x=50;
y=50;
function='PIE';
style='SOLID';
angle=0;
line=1;
rotate=360;
size=(&radius.*((39)/100));
color='CX2F3338';
output;
run;

data hole2; set ex2;
length style function color $ 12;
xsys='3'; ysys='3'; hsys='3';
x=50;
y=50;
function='PIE';
style='SOLID';
angle=0;
line=1;
rotate=360;
size=(&radius.*((36)/100));
color='CX415D8E';
output;
run;

/* 天 使 圈 */
data circle1; set ex2;
length style function color $ 12;
xsys='3'; ysys='3'; hsys='3';
x=50;
y=50;
function='PIE';
style='SOLID';
angle=0;
line=1;
rotate=360;
size=(&radius.*((148)/100));
color='CX2E2E2E';
output;
run;
data circle2; set ex2;
length style function color $ 12;
xsys='3'; ysys='3'; hsys='3';
x=50;
y=50;
function='PIE';
style='SOLID';
angle=0;
line=1;
rotate=360;
size=(&radius.*((145)/100));
color='CX232323';
output;
run;

/* 饼周围的外线 */
data outlines; set pies hole1;
style='EMPTY';
color="CX6C6C6C";
line=3;
run;

/* 标注每个 PIE */
data slices; set pies; by index;
if first.index then output;
run;
data slices; set slices;
length text $10;
/* 定位到PIE的正上方的角度 */
function='piexy'; angle=angle+rotate*.5;
/* 定位到PIE的正上方的位置距离 */
size=5; output;
/* 转换坐标 */
function='cntl2txt'; output;
/* 在定义好的地方进行标注 */
function='label'; text=index||index||index; angle=0; rotate=0; color='CX776122';
style='"arial/bo"'; size=3; x=.; y=.; position='5';
output;
run;

/* 标注中心 地方 */
data center;
length style function color $ 12;
length text $12;
xsys='3'; ysys='3'; hsys='3';
x=50;
y=50;
function='LABEL';
color='CXF1F9FF';
text='facebook';
position='B';
style='"arial/bo"'; size=3.5;
output;
run;

/*data anno; set circle1 circle2 center pies outlines hole1 hole2 slices ; run;*/

data anno; set circle1 circle2 center pies outlines hole1 hole2 slices; run;

ODS LISTING close ;

ODS HTML path=file body="&name..htm" ;
goptions reset=all noborder
xpixels=4000 xmax=3in ypixels=4000 ymax=3in
device=JPEG300 gsfname=file cback=CX242424;

proc ganno annotate=anno name="&name"; ;
run;

quit;

ods HTML CLOSE;
ODS LISTING ;

《用SAS实现堆积式南丁格尔玫瑰图Nightingale Rose Diagram (上)》上有7条评论

  1. 一个其他小问题:
    用这种代码高亮方式的话,直接复制下来,英文引号会全部变为中文引号,得全部手动改,有点麻烦啊…

发表评论

电子邮件地址不会被公开。 必填项已用*标注