20 Julia统计图形—Gadfly

20.1 介绍

Julia语言没有内建作图能力, 作图需要通过扩展包提供, 因为Julia语言的历史还比较短, 现在有多种作图用的扩展包但是没有一个占绝对优势的包。 比较常用的有Gadfly, Plots, PyPlot包。 Julia还在快速发展阶段, 功能的兼容性不够稳定, 作图功能尤其如此。 本文演示Gadfly包作图。

本文作者先安装了Anaconda3, 然后安装Julia1.4。 在使用Jupyter界面时, Gadfly支持将图形结果直接显示到“笔记本”页面中。 在使用Juno界面时, 可以将作图结果显示在Atom编辑器的一个窗格中。

Gadfly包是模仿了R语言的ggplot2包的做法, 其作图函数设计比较典雅, 按照一种专门图形语言的方法设计, 作图结果比较美观, 图形类型也比较丰富。 参见本文作者R语言教程中的ggplot作图介绍:

Gadfly包的文档:

linspace(from, to, n) = range(from, to, length=n)

作图需要用一些例子数据。 如下的class.csv中包含了19个学生的姓名、性别、年龄、身高、体重信息:

name,sex,age,height,weight
Sandy,F,11,130,23
Karen,F,12,143,35
Kathy,F,12,152,38
Alice,F,13,144,38
Becka,F,13,166,44
Tammy,F,14,160,46
Gail,F,14,163,41
Sharon,F,15,159,51
Mary,F,15,169,51
Thomas,M,11,146,39
James,M,12,146,38
John,M,12,150,45
Robert,M,12,165,58
Jeffrey,M,13,159,38
Duke,M,14,161,46
Alfred,M,14,175,51
William,M,15,169,51
Guido,M,15,170,60
Philip,M,16,183,68

读入:

using CSV, DataFrames
d_class = CSV.read("class19.csv", DataFrame)

19 rows × 5 columns

name sex age height weight
String7 String1 Int64 Int64 Int64
1 Sandy F 11 130 23
2 Karen F 12 143 35
3 Kathy F 12 152 38
4 Alice F 13 144 38
5 Becka F 13 166 44
6 Tammy F 14 160 46
7 Gail F 14 163 41
8 Sharon F 15 159 51
9 Mary F 15 169 51
10 Thomas M 11 146 39
11 James M 12 146 38
12 John M 12 150 45
13 Robert M 12 165 58
14 Jeffrey M 13 159 38
15 Duke M 14 161 46
16 Alfred M 14 175 51
17 William M 15 169 51
18 Guido M 15 170 60
19 Philip M 16 183 68

Gadfly用plot()函数作各种图。 可以用Gadfly.plot()避免冲突, 如果没有其它作图包, 可以直接使用plot()

20.2 条形图

对分类变量, 在进行频数统计后可以做频数条形图。 比如,性别的条形图:

using Gadfly, DataFrames
dc_freq1 = groupby(d_class, :sex) |>
    gdf -> combine(gdf, nrow => :Freq)

2 rows × 2 columns

sex Freq
String1 Int64
1 F 9
2 M 10
Gadfly.plot(dc_freq1, x=:sex, y=:Freq, color=:sex, Geom.bar())

与R语言的hist()函数相比, Gadfly的直方图判断分组数的功能较弱, 而且分组也不选择分在数字比较整齐的位置。

用如下程序作核密度估计图:

Gadfly.plot(d_class, x=:height, Geom.density())

20.3 盒形图(Boxplots)

盒形图又称箱线图、盒须图等。用Geom.boxplot()。 如

dtmp = copy(d_class)
dtmp[!,:grp] .= ""
Gadfly.plot(dtmp, x=:grp, y=:height, Geom.boxplot(),
  Guide.xlabel(""))

盒形图中x=是分组用,如

Gadfly.plot(d_class, x=:sex, y=:height, Geom.boxplot())

小提琴图是一种变种的盒形图, 其边界用了核密度曲线,如:

Gadfly.plot(d_class, x=:sex, y=:height, Geom.violin())

20.4 散点图

对数据集中两个变量xy,用类似下面的程序作散点图:

Gadfly.plot(d_class, x=:height, y=:weight)

可以用color选项指定按照某个变量的值添加不同颜色:

Gadfly.plot(d_class, x=:height, y=:weight, color=:sex)

可以用shape指定一个变量, 用不同形状的点表示该变量的不同值:

Gadfly.plot(d_class, x=:height, y=:weight, shape=:sex)

可以为散点图增加Loess局部多项式平滑曲线:

x = round.(5*rand(30), digits=1)
y = 200 .+ 2 .* x .^2 .+ 2*randn(30)
Gadfly.plot(x=x, y=y, Geom.smooth(), Geom.point(),
  Guide.title("二次多项式用局部回归平滑"))

除了可以用Guide.title()增加标题, 还可以用Guide.xlabel()指定x轴标签, 用Guide.ylabel()指定y轴标签。

20.5 折线图

Geom.line()指定折线图, 要求横坐标数据从小到大排列。 如

dtmp = copy(d_class)
sort!(dtmp, :height)
Gadfly.plot(dtmp, x=:height, y=:weight, Geom.line())

20.6 函数曲线

输入一个一元函数,指定区间, 可以对其做函数曲线,如

Gadfly.plot(sin, 0, 10*pi)

将多个函数组成一个向量, 可以做多个函数的图形:

Gadfly.plot([sin, cos], 0, 10*pi)

无名函数的图形:

Gadfly.plot(x -> exp(-x) * sin(2*pi*x), 0, 5)

也可以对二元函数作等值线图,如

Gadfly.plot((x,y) -> exp(-(x^2 + y^2)) * sin(2*pi*(x^2 + y^2)), 
    -1, 1, -1, 1)