之前已经简单介绍过一次如何使用 Bokeh-scala 进行数据可视化(见),以及如何在 Geotrellis 中进行分布式下的空间数据可视化(见),但是之前介绍的只是简单的线、圆圈等可视化方式,本文位大家介绍几种高级的可视化图表。
整体上与第一篇 Bokeh-scala 文章中介绍的方式相同,主要是完善了 BokehHelper 类,我已经将所有代码放在 Github 中(见)。
2.1 柱状图
柱状图主要是创建一个 Quad 对象,代码如下:
- val quad = new Quad().left(left).right(right).bottom(bottom).top(top).fill_color(fill_Color).line_color(line_Color)
其中 left 表示左边柱状图的每一根柱子的左侧 x 数据,right 表示右侧 x 数据,top 表示上侧 y 数据,bottom 表示下侧 y 数据,理论上最好取每个 right 值为下一个的 left 值,这样整个柱状图刚好能左右衔接在一起。当然如果只有光秃秃的 "柱子" 没有任何说明也完全不能表达出柱状图的效果,我们可以使用 Text 类来创建文本对象添加到 "柱子" 的上方,代码如下:
- val textPosition = column(left.value.map(_ + 0.4)) BokehHelper.setTextGlyph(plot, textPosition, top, text, source)
其中 textPosition 为文本显示的左侧位置,这里采用 "柱子" 左侧值加 0.4 的结果,这样就可以得到一个漂亮的柱状图。text 图元会在下面详细介绍。效果如下图:
2.2 饼状图
饼状图主要是创建一个 AnnularWedge 对象,代码如下;
- val annularWedge = new AnnularWedge().x(x).y(y).inner_radius(innerRadius).outer_radius(outerRadius).start_angle(startAngle).end_angle(endAngle).fill_color(Color.Blue).line_color(Color.Red).direction(Direction.Clock)
其中 x 为饼状图显示的 x 坐标,y 为饼状图显示的 y 坐标,inner_radius 为内圆半径,outer_radius 为外圆半径,start_angle 为起始角度,end_angle 为结束角度,direction 为圆弧的方向。其中 inner_radius、outer_radius、start_angle、end_angle 均可以是序列或单个值,如果是单个值表示每一个 "饼" 采用相同的值,如果是序列表示每一个 "饼" 采用不同的值。此处需要注意的是 0 度位置为水平向右,最大值为 2π,最小值为 - 2π,逆时针方向,所以一般情况应当是 start_angle 对应的值小于 end_angle 对应的值,当然可以通过设置 direction 的值为 Direction.Clock 来改变角度大小对应关系(direction 的值默认为 Direction.AntiClock),而且在实际测试中我发现当 direction 设置为 Direction.AntiClock 时,将不会有任何内容的图表产生,此处应当是个 BUG。
同理我们此处也可以为每个 "饼" 添加一个文本标记用以区分,此处稍有不同的是由于标记是在一个圆圈周围,需要根据三角函数来计算文本的 x、y 值,并为文本设置对应的角度。代码如下:
- val textAngle = column(startAngle.value.map(_ + 0.3 / 2)) val text_x = column(textAngle.value.map(6 * Math.cos(_))) val text_y = column(textAngle.value.map(6 * Math.sin(_))) println(text_x.value) println(text_y.value) BokehHelper.setTextGlyph(plot, text_x, text_y, text, source, angle = textAngle)
由于我的测试数据为结束角度比起始角度大 0.3 所以文本角度取起始角度加 0.15 使其刚好在每个 "饼" 的中间位置。text_x 就是根据每一个角度计算 cos 值并乘以外圆半径,text_y 就是根据每一个角度计算 sin 值并乘以外圆半径,最终并为 text 对象赋一个角度 angle。text 图元象的实现代码如下:
- val text = new Text().x(x).y(y).text(t).angle(angle)
其中 x 为显示的 x 坐标,y 为显示的 y 坐标,text 为显示的文本内容,angle 为文本角度,x、y、t、angle 均为序列值,可以在图表中放置一系列的不同文本。通过以上代码就能实现一个漂亮的饼状图。效果如下图所示:
2.3 区域图
这里的区域图的意思就是面积覆盖图,简单的说就是一组坐标点相连(首尾也相连)包裹起来的范围,我们先来看一下效果图。
其中每种颜色代表一个面积区域,实现区域图只需创建一个 Patches 对象。实现代码如下:
- val xs = column(IndexedSeq[List[Double]](List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10), List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10), List(1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10))) val ys = column(IndexedSeq[List[Double]](List(0, 8, 9, 8.8, 8.6, 8.5, 8, 9, 8.9, 9.8, 8.5, 0), List(0, 3, 5, 6, 7, 5, 4, 3, 3.6, 4.5, 5.5, 0), List(0, 1, 2, 1, 3, 2.5, 2.8, 3, 1.9, 2, 3, 0))) val patches = new Patches().xs(xs).ys(ys).line_width(width).line_color(line_Color).fill_color(fill_Color).fill_alpha(0.8)
其中 xs 表示 x 值序列,ys 表示 y 值序列。这里需要特别说明的是 xs 和 ys 内部又由多个 List 组成,这样相当于每个 List 对应上图中的一种颜色。xs 与 ys 中 List 个数要相等,并且每个 List 中的元素个数也要相等,相当于每一个 x 坐标均对应一个 y 坐标,这样就会出现多组坐标首尾相连。实际中最好将每个 List 中的 x 的第一个值和最后一个值重复添加,并将对应的 y 值设为 0,这样相当于坐标点的首和尾均在 x 轴上,效果会更好,并且最好将 y 值整体较小(或者大,取决于上述水平线的位置)的 List 放在后面,作用是区域叠压的时候小的区域在上部,不会被压盖住使得该区域不可视。也可以为每组 List 设置不同的 fill_color,可以得到不同的填充效果。
2.4 地图
有时候需要在地图中添加城市等坐标点信息,这个在 Bokeh 中也很容易实现,代码如下:
- new GMapPlot().x_range(xdr).y_range(ydr).tools(tools).width(width).height(height) val map_options = new GMapOptions().lat(30.2861).lng( - 97.7394).zoom(2).map_type(MapType.Roadmap) plot.map_options(map_options) BokehHelper.setCircleGlyph(plot, lon, lat, source)
首先创建 plot 对象就与普通图表不同,这里要创建一个 GMapPlot 对象,然后要创建一个 GMapOptions 对象,用于设置地图的一些常用属性,如显示的层级以及显示的经纬度坐标等。有了 GMapPlot 对象,就可以像之前创建其他可视化图元那样创建在地图上的可视化图元,如点、线、面等。效果如下图所示:
当然其地图采用了 Google 地图,所以你可能需要做些其他操作(Over wall)才能看到。
2.5 交互式信息提示
如果在鼠标移动到某个图元的时候能够动态的提示相应的信息,这样会带来很好的客户体验,在 Bokeh 中实现起来也很容易,只需要添加一个 HoverTool 的工具即可,实现代码如下:
- val hover_tool = new HoverTool().tooltips(Tooltip("value" - >"@x0", "name" - >"@text")) plot.tools: =hover_tool: :new PanTool: :new WheelZoomTool: :Nil
其中 tooltip 为设置提示内容,这里采用键值对的方式,key 为要提示的信息名称,value 为要提示的信息内容,@text 采用了通配符的方式,即图表会自动从为该图元赋值时的 source 类中寻找名为 text 的变量并赋值给对应的图元,这样当鼠标移动到图元中时就会得到相应的提示信息。效果如下图所示:
以上是部分 bokeh-scala 数据可视化的高级图表,全部代码见,后续还会逐步完善,小功能或 BUG 修改会直接推送到 Github 中,大的功能实现或讲解可能会重写一篇博客介绍。欢迎探讨、交流。
来源: http://www.cnblogs.com/shoufengwei/p/5794503.html