在Excel中做这种图,需要一些技巧,今天整理一下这个问题。主要的技巧是:将其中一列数据转换为负数,使之出现在分类轴的左边,同时使用自定义数据格式将负值显示为正数。
做法与步骤:
1、对原数据B~D列,准备转换数据如F~H列,其中G列=-C列,I~K列为较高级辅助数据,后面再说。

2、以F~H列数据作堆积条形图。

3、这时,分类轴的分类项目次序与表格相反,可在坐标轴->主要纵坐标轴->坐标卓选项->勾选“逆序类别”,这个地方是一个小技巧。

4、在纵坐标轴的坐标轴格式中设置刻度线标签在图外。
5、删除数值轴。如欲保留数值轴,注意由于左边是负的,需要调整显示为正数,方法:数值标签->格式->数字->自定义->0.0;0.0;0.0,这个地方是关键技巧之一,后面也要用到。
6、设置显示左右条形图的数值标签,并调整到合适位置。对左边的负值标签需要使用上面的自定义数据格式技巧,使之显示为正数。
7、如觉得第6步手动调整麻烦,该步骤可使用以下高级方法替代:借用辅助序列显示标签值。方法是:分别将j列和k列的辅助数据加入图表,这时左右条形图顶端各出现一个新的序列,设置其无框、透明,使用标签修改工具宏,分别设置其数据标签为 C列和D列,则左右条形图的数值标签位置非常好了,也没有负数烦恼了。参见后面的隐形辅助序列显示出来的情况。
8、进行其他格式化,达到下图效果,不一一细述。

用SAS实现这个图有3个要点:
1、标记对比的两个组的名称(此处为“Worst Case”,“Best Case”),这用note来实现。
2、横坐标的负值部分需要显示成正值形式。首先将需要在这个区域显示的值变成等值负的形式(用一个data步实现),然后用format语句改变显示格式,这点有点像Excel的实现方法。
3、让实际值标注在条柱附近。这个用anno来解决。
代码如下:
goptions reset=(global goptions); goptions device=png xpixels=800 ypixels=600; goptions gunit=pct border cback="#F7EEE7" colors=(BLACK) ctext=BLACK noborder hsize=3.5 vsize=3 htitle=6.5 htext=3; data demo; input class$ type$ amount; cards; 分类项1 Bcase 0.5 分类项1 Wcase 0.957 分类项2 Bcase 0.84 分类项2 Wcase 0.775 分类项3 Bcase 0.6 分类项3 Wcase 0.598 分类项4 Bcase 1.06 分类项4 Wcase 0.38 分类项5 Bcase 0.21 分类项5 Wcase 0.18 分类项6 Bcase 0.18 分类项6 Wcase 0.12 分类项7 Bcase 0.35 分类项7 Wcase 0.04 分类项8 Bcase 0.24 分类项8 Wcase 0.16 ; run; data demo; set demo; if type='Wcase' then amount=-amount; run; proc format; picture posval low-high='9.999'; run; data anlabels(drop=class type amount); length text $ 8; retain function 'label' when 'a' xsys ysys '2' hsys '3' size 4; set demo; midpoint=class; subgroup=type; text=left(put(amount,posval.)); if type ='Wcase' then position='<'; else position='>'; output; run; ods listing; title1 '旋风图(DEMO)'; footnote1 justify=left 'Created by Jonee'; footnote2 justify=left "&sysdate9."; axis1 label=(justify=left 'class') value=(tick=2 ) style=0 color=BLACK width=2; axis2 label=none value=(tick=2 '') minor=none major=none width=1 order=(-1.5 to 1.5 by 0.5) color=BLACK; pattern1 value=solid color="#C5C3C6"; pattern2 value=solid color="#A10003"; proc gchart data=demo; format amount posval.; note move=(36,88) height=4 'Worst Case' move=(+5.5,+0) 'Best Case'; hbar class /sumvar=amount discrete nostat subgroup=type maxis=axis1 raxis=axis2 nolegend annotate=anlabels coutline=same; run; quit;
输出结果:

 
                    
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号