把資料做得更好看2——Echarts柱狀圖的組合擴充和選區聚焦(Python資料視覺化)

賜我開心面具發表於2020-12-26

前言:本文是在把資料做得更好看1——Echarts基礎柱狀圖繪製&渲染&PPT聯動(Python資料視覺化)的基礎上的擴充和進階,對pyecharts不熟悉的童鞋可以參考上面的連結。

1.柱狀圖的組合擴充

柱狀圖作為較為基本的統計圖表,所能涵蓋的資訊有限。但如果能在柱狀圖的基礎上增添一些標記功能或者形成多種圖表的組合,就會讓柱狀圖的層次感大大提升。快進到正文。

1.1 柱狀圖的標註

為柱狀圖新增標註,首先要了解與標註相關的配置項,pyecharts中主要有如下配置項與標註有關:

配置項功能
MarkPointItem:標記點資料項標註的型別(特殊型別:最大,最小,均值);標註的形狀(圓形,三角,圖片等);標註的大小及座標等
MarkLineItem:標記線資料項同標記點資料項
MarkAreaItem: 標記區域資料項同標記點資料項

下面結合一些例項,康一康如何給柱狀圖新增標註。(偷個懶,測試程式碼採用了Faker函式,即資料為隨機生成。)

1.1.1 標記點

from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.faker import Faker

c = (
    Bar()
    .add_xaxis(Faker.choose())
    .add_yaxis("某寶", Faker.values())
    .add_yaxis("並夕夕", Faker.values())
    .set_global_opts(title_opts=opts.TitleOpts(title="不同型別的標記點"))
    .set_series_opts(
        label_opts=opts.LabelOpts(is_show=False),  # 關閉標籤顯示使得標註點更明顯
        markpoint_opts=opts.MarkPointOpts(
            data=[
                opts.MarkPointItem(type_="max", name="最大值", symbol="pin"),
                opts.MarkPointItem(type_="min", name="最小值", symbol="circle"),
                opts.MarkPointItem(type_="average", name="平均值", symbol="arrow"),
            ]
        ),
    )
    .render("bar_markpoint.html")
)

在這裡插入圖片描述
這裡說幾個經驗和感受:
1.預設標記點的symbol是pin,實測下來確實也是pin最好看,其他需要手動調相對位置才比較能看,建議直接用預設值就好。
2.關於type的average,雖然表面是均值,但實測下來它的含義更像中位數,所以當你的組數為偶數時,這個標記點時有時無。我暫時還沒有摸清楚邏輯,但最好的解決方法是用標記線標記均值。

1.1.2 標記線

標記線的定義方式與標記點幾乎一致:

markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average", name="平均值", symbol="circle"),]),)

就得到了均值的線(symbol定義的是這條線起始點形狀,不是修改終點的箭頭)
在這裡插入圖片描述
當然,在資料分析時,除了最值和均值,我們也需要標註一些其他值(比如閾值,異常值等),這就需要我們自定義標記線。這裡可以結合numpy中的一些函式做簡單的資料處理,舉個例子。

from pyecharts import options as opts
from pyecharts.charts import Bar
import numpy as np

data = [90, 20, 36, 10, 75, 5]
bar = (
        Bar()
        .add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])
        .add_yaxis("商家A", data)
        .set_global_opts(title_opts=opts.TitleOpts(title="自定義標記線"),)
        .set_series_opts(markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(y=np.mean(data)/2), ]),)
        # 標定均值的一半視作異常值
)

bar.render("sta1.html")

在這裡插入圖片描述
至於標記線的外觀也可以定義,使之更有區分度。

bar=(   
Bar()
.set_series_opts(markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(y=np.mean(data)/2)],
                 linestyle_opts=opts.LineStyleOpts(type_="dotted", width=3, color="#00BFFF"))
)

在這裡插入圖片描述

1.1.3 標記區域

有時候我們也需要對區域進行分塊操作,比如把12個月分為四個季度,就可以採用標記區域的方法進行分隔。

from pyecharts import options as opts
from pyecharts.charts import Bar

data = [90, 20, 36, 10, 75, 5]
bar = (
        Bar()
        .add_xaxis(["襯衫", "羊毛衫", "羽絨服", "褲子", "高跟鞋", "襪子"])
        .add_yaxis("商家A", data)
        .set_global_opts(title_opts=opts.TitleOpts(title="自定義標記區域"))      .set_series_opts(markarea_opts=opts.MarkAreaOpts(data=[opts.MarkAreaItem(name="秋冬季", x=("羊毛衫", "羽絨服"))],
                        itemstyle_opts=opts.ItemStyleOpts(color="#00BFFF", opacity=0.3)),)
)
bar.render("sta1.html")

在這裡插入圖片描述
(醜是醜了點,意思是那個意思,Cover區域可以調節位置引數,不好意思我又懶了)

1.2 柱狀圖的擴充

柱狀圖的擴充多種多樣,下面主要介紹多軸的柱狀圖,含有圖片資訊座標軸的柱狀圖和柱狀圖和折線圖的組合。

1.2.1 多軸柱狀圖

製圖中經常會遇到多個y軸,但單位或者刻度不同的情況,就需要在一張圖表中建立多個y軸。
在建立多軸之前,需要意識到建立圖表會有一條在左側的預設y軸,所以我們的多軸工作可以拆分成兩個部分:一是將預設的y軸設定成我們想要的樣子,需要用到set_global_opts下的yaxis_opts(如果要求不高,可以直接在add_yaxis時設定引數);二是新增額外的座標軸並設定引數,需要用到extend_axis。
結合程式碼,看一個例項:

import pyecharts.options as opts
from pyecharts.charts import Bar

colors = ["#FFA07A", "#778899"]
x_data = ["一季度", "二季度", "三季度", "四季度"]
legend_list = ["支出", "存款"]
expense = [12000, 8000, 15000, 9000]
deposit = [25, 27, 30, 29]

bar = (
    Bar()
    .add_xaxis(xaxis_data=x_data)
    # 新增支出軸
    .add_yaxis(series_name="支出", y_axis=expense, color=colors[0])
    # 利用全域性配置項對預設軸進行修改
    .set_global_opts(yaxis_opts=opts.AxisOpts(
            type_="value", name="支出", min_=6000, max_=16000,
            axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color=colors[1])),
            axislabel_opts=opts.LabelOpts(formatter="{value}元"))
    )
    # 新增收入軸
    .add_yaxis(series_name="存款", y_axis=deposit, yaxis_index=1, color=colors[1])
    # 利用extend_axis新增新軸
    .extend_axis(yaxis=opts.AxisOpts(
            type_="value", name="存款", min_=20, max_=32, position="right",
            axisline_opts=opts.AxisLineOpts(
                linestyle_opts=opts.LineStyleOpts(color=colors[0])),
            axislabel_opts=opts.LabelOpts(formatter="{value} 萬元"))
    )
    # 交叉指向,資料按照座標軸區分
    .set_global_opts(tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross")))
bar.render("multiple_axes.html")

在這裡插入圖片描述
再次說明一下,看起來有些區別對待的操作原因:你只要定義了Bar,即便沒有填充任何資料,初始的橫軸縱軸已經生成。這個初始的軸只能通過全域性配置項修改。更好的辦法就是對於這個初始的軸少些騷操作,讓它可以通過add_x(y)axis就完成定義。

1.2.2 柱狀圖與折線圖的組合

作為直角座標系的兩類經典圖表,柱狀圖與折線圖有較好向性,當然其他直角座標系圖表之間也有較好搭配,核心思想都是運用overlap函式,這裡只是試舉此例。

from pyecharts import options as opts
from pyecharts.charts import Line, Bar

x_data = (["一季度", "二季度", "三季度", "四季度"])
wage = [6500, 7000, 8000, 7500]
extra_gains = [2000, 2200, 1800, 3200]
# 柱狀圖繪製
bar = (
    Bar()
    .add_xaxis(x_data)
    .add_yaxis("工資", wage)
    .add_yaxis("外快", extra_gains)
    .set_global_opts(title_opts=opts.TitleOpts(title="收入情況"),
                     tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"))
)
# 折線圖繪製
revenue_line = (
    Line()
    .add_xaxis(xaxis_data=x_data)
    .add_yaxis(series_name="總收入", y_axis=[wage[i]+extra_gains[i] for i in range(len(wage))])
)
# overlap合併
bar.overlap(revenue_line).render("bar&line.html")

在這裡插入圖片描述
其實,overlap只是較為簡單的堆疊,pyecharts中定義了包括Grid(並行多圖),Page(順序多圖),Tab(選項卡多圖),以及Timeline(時間線輪播多圖)等更為複雜的圖表組合關係。有時間的話,我一定補上。

1.2.3 formatter的使用

很多時候,生成圖表資訊往往有限,有辦法讓它更豐富嗎?或許可以。熟練使用formatter甚至rich(富文字),可以讓你有更豐富的標籤展示。篇幅原因,這裡簡單談一談,或許等我摸得更透再寫一篇。(瘋狂挖坑
比如圖中X軸的字首,是B(後衛)還是F(鋒線)的判斷就可以通過formatter實現。

在這裡插入圖片描述

from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.commons.utils import JsCode

colors = ["#FF6347", "#FFFFFF"]
x_data = ["Salah", "Jota", "Mane", "Firmino", "Robertson", "Arnold"]
goal = [16, 9, 6, 5, 1, 0]
assist = [4, 0, 3, 3, 5, 4]
c = (
    Bar(init_opts=opts.InitOpts(width="1000px", height="680px",
        bg_color={"type": "transparent", "image": JsCode("img"), "repeat": "repeat"}))
    .add_xaxis(x_data)
    .add_yaxis("進球", goal, color=colors[0])
    .add_yaxis("助攻", assist, color=colors[1])
    .set_global_opts(
        xaxis_opts=opts.AxisOpts(
                                 axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color=colors[0])),
                                 axislabel_opts=opts.LabelOpts(
                                     # 通過formatter進行判斷,為標籤豐富資訊
                                     formatter=JsCode("function(value)"
                                                      "{if (value==='Robertson'||value==='Arnold') {return 'B:'+value} "
                                                      "else {return 'F:'+value}}")
                                 )
                                 ),
        yaxis_opts=opts.AxisOpts(axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color=colors[0]))),
        legend_opts=opts.LegendOpts(textstyle_opts=opts.TextStyleOpts(color=colors[1])),
        title_opts=opts.TitleOpts(title="利物浦20賽季隊內資料統計", title_textstyle_opts=opts.TextStyleOpts(color=colors[0])))
)
c.add_js_funcs(
    """
    var img = new Image(); img.src = 'liverpool.jpeg';
    img.width="80%";
    img.height="80%";
    """
)
c.render("liverpool.html")

當然,formatter和rich的應用遠不如此,比如官方案例中的將座標軸值設為圖片。這一部分的一些操作,餅狀圖更易實現,且需要一些JS的知識,下次寫到再說了。(實際上是柱狀圖我難以實現,如果有大佬可以在評論區教我一下)
在這裡插入圖片描述

2. 柱狀圖的選區聚焦

在展示過程中,總會遇到需要聚焦某一部分資料的情況,這個時候就要我們把圖表的一部分有重點的呈現。具體來說,選區有種情況,一種是手動選區,類似於截圖的選區操作;另一種是縮放選區,比如篩選一段時間或者一定範圍內的資料。捯飭起來。

2.1 手動聚焦

主要利用brush工具,包含矩形選區和圈選。
在這裡插入圖片描述

from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.faker import Faker

c = (
    Bar()
    .add_xaxis(Faker.choose())
    .add_yaxis("商家A", Faker.values())
    .add_yaxis("商家B", Faker.values())
    .set_global_opts(
        title_opts=opts.TitleOpts(title="動態選區"),
        brush_opts=opts.BrushOpts(),
    )
    .render("brush.html")
)

2.2 縮放聚焦

縮放的控制元件分為外部控制元件和內部控制元件,外部控制元件通過一個軸控制,內部控制元件通過滑鼠滾輪控制,先看效果。
在這裡插入圖片描述

from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.faker import Faker

c = (
    Bar()
    .add_xaxis(Faker.days_attrs)
    .add_yaxis("商家A", Faker.days_values, color=Faker.rand_color())
    .set_global_opts(
        title_opts=opts.TitleOpts(title="縮放聚焦"),
        datazoom_opts=[opts.DataZoomOpts(range_start=20),  opts.DataZoomOpts(type_="inside")],
        # 前項是新增控制軸,後項是內建控制區。range_start為資料視窗範圍的起始百分比。
    )
    .render("datazoom.html")
)

當然對於起始視窗的定位,也可以用start_value定位,但它的優先順序低於range_start,即宣告range_start後再宣告start_value就無效了。

同樣可以做y軸的縮放聚焦:

 datazoom_opts=opts.DataZoomOpts(orient="vertical")

在這裡插入圖片描述
這些動態的內容如何嵌入彙報PPT呢,可以參照把資料做得更好看1——Echarts基礎柱狀圖繪製&渲染&PPT聯動(Python資料視覺化)

謝謝您辛辛苦苦看到這,眼看就要到新的一年了,是不是缺少朋友圈發圖素材呢。下一次打算寫一寫如何做一些年終總結的圖表(好看的那種),只要我不咕,一定會加速整起來的!

相關文章