谢钢
我帮助学生用R画了一个漂亮的条形图(bar chart)
2023-11-5 18:15
阅读:3032

  我现在的工作主要是为全校的研究生及教职工研究人员提供统计数据分析的咨询及支持,包括回答一般性的关于统计理论及数据分析的问题、在具体的统计分析模型及软件的使用上提供咨询帮助、对他们的论文或投稿文章的统计分析方法及应用部分提改进意见或作编辑修改甚至作投稿文章的共同作者(co-author)、每年定期或不定期作各种关于统计软件应用或统计分析专题(例如回归树及分类树模型、时间序列分析、统计功效、Rasch Model、贝叶斯网络等等)的讲座或短训班。每年处理的大大小小的的统计咨询项目都在5080个(其中新增加的项目约为每年3060个)左右。

最近有一个农业科学兽医专业的博士生到了写论文的阶段了,遇到了两个具体的关于用R作数据分析的问题需要我的帮助。她的第二个问题是无法用R将数据画出需要的一个比较复杂的条形图,她说已经试了在网上找答案、问ChatGPT要答案,结果都未能成功,这让我感到有点奇怪。于是我让她把数据及想画的条形图的样板给我看看是怎么一回事。

这位博士生要画条形图的数据是关于某种牲畜疾病(Q-fever)的六种不同状态条件(six scenarios)下的三个变量的五级水平的李克特量值(five-point Likert scale)。因此每一个变量都对应一个有六个成分累加条形(每个条形代表一种状态条件下的一个五级李克特量值的分布)组成的条形图。她要求这些条形图要呈水平状态以百分比的结果显示;由于每个状态条件所得到的数据点的数量不完全相同,所以还要把对应的数据量的信息也标注在对应的条形上;最好能把三个变量的条形图画在同一张图上(it is better to put three bar plots in one graph)

拿到数据后我首先就发现了她的数据文件的格式不符合画条形图的数据格式要求。于是先将数据格式的问题解决,再用R把画条形图所要求的二维列联频率表算出来。第三步二维列联频率表用相应的百分比数值表示(即将二维列联频率表分别除以各列的总频率数再乘100);第四步把每一个变量的条形图画出来并在颜色图标、坐标轴/数轴标识等细节之处作调整确定;最后用R把三个条形图整合在一张图里。我还特别多写了几行R代码,使得该博士生可以选用不同的颜色组合来画条形图。

在把我的画条形图的R解决方案给了这位博士生后,她顺利地用我提供的R代码在她自己的计算机上把图画了出来,她对结果十分满意。这就是我为研究生们提供统计数据分析的咨询及支持服务的一个小小的案例。

以下是一些我所给出的解决方案的具体技术细节供有兴趣的读者参考。

 

如果以一个二维列联频率表作为画条形图的输入信息,Rbarplot()绘图函数的默认设置给出的是这样的结果(R代码及绘制的条形图)。

outq1 = with(dataSq1, table(values,scenarios))

barplot(outq1)

二维列联频率表用相应的百分比数值表示,并使得条形图以水平方式显示;并把图标、坐标轴/数轴标识等信息加上。这样得出的绘图结果为:

 

xx = as.numeric(apply(outq1,2,sum))

 for(i in 1:6) {outq1[,i]=outq1[,i]/xx[i]*100 }

cscheme = c("grey95","grey85","grey70","grey45","grey25","grey5")

barplot(outq1, horiz=T, col=cscheme,  

    xlab="Respondents(%)",ylab="Scenarios",xlim=c(0,150),axes=F)

axis(1, at=c(0,20,40,60,80,100))

legend ( 110,4,c("Very_low_risk","Low_risk","Unsure","High_risk","Very_high_risk"),

    col=cscheme,  pch=15, bty="n")

最后把三个条形图画在同一张图上,首先要把三张二维列联频率表用相应的百分比数值的结果算出来,如下表所示:

 

再按以下的R代码就可将合并的条形图画出,并把结果输出成为一个.jpg的图像文件:

请注意到在上面的R代码中一些作了进一步细微调整改进的地方,比如,条形图绘图语句中las=1使得竖轴的标识S1 S2,等等变成了水平显示,并加入了数据点数量的信息n=35, n=32, 等等。

barplot(outq1, horiz=T, col=cscheme, xlab="", ylab="Scenarios: risk",xlim=c(0,125),axes=F,las=1)

 axis(2, at=c(0.3,1.5,2.7,3.9,5.1,6.3), lab=c("n=35","n=32","n=33","n=55","n=54","n=53"),las=1)

以下这两行代码则是把三个条形图合成了一张图。

nf = layout(matrix(c(1,2,3),3,1,byrow=T))

layout(1)  # back to default setting

更细微的关于单个条形图与数轴之间及其彼此之间的相对位置关系或间隔距离大小等等的调整则是由这两条条代码处理了:

op = par(mar=c(5,5,0.5,0.2),mgp=c(3,0.8,0))

par(op)

 

下面这个图就是被博士生采用了放在她的论文中的条形图。

我提醒了这位博士生,如果需要,她还可以选择不同的颜色组合来画条形图。相关的R代码如下。