1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Matplotlib玩轉(zhuǎn)動(dòng)態(tài)可視化

        共 5627字,需瀏覽 12分鐘

         ·

        2020-09-16 01:13

        最近看到很多盆友們用pyecharts、Bokeh和plotly等繪圖庫制作動(dòng)態(tài)圖,還有用pbi制作的,以及網(wǎng)頁工具flourish等。其實(shí)matplotlib這個(gè)經(jīng)典繪圖庫也是可以的,這不就來了嘛~

        目錄

        • 1.效果預(yù)覽
        • 2.數(shù)據(jù)獲取
        • 3.數(shù)據(jù)預(yù)處理
        • 4.matplotlib動(dòng)態(tài)可視化

        1.效果預(yù)覽

        我們從國家統(tǒng)計(jì)局 下載最近30年全國各地區(qū)生產(chǎn)總值(實(shí)際上是1993年-2019年),使用matplotlib繪制動(dòng)態(tài)可視化圖,效果如下:

        2.數(shù)據(jù)獲取

        直接從國家統(tǒng)計(jì)局-「國家數(shù)據(jù)」(http://data.stats.gov.cn/)下載原始數(shù)據(jù)即可,數(shù)據(jù)長這樣:

        3.數(shù)據(jù)預(yù)處理

        #?需要引入的庫
        import?pandas?as?pd
        import?matplotlib.pyplot?as?plt
        import?matplotlib.ticker?as?ticker
        import?matplotlib.animation?as?animation
        from?IPython.display?import?HTML

        原始數(shù)據(jù)的行索引是地區(qū),列索引是年份,我們后續(xù)作圖需要的數(shù)據(jù)結(jié)構(gòu)偏向于窄表(當(dāng)然寬表其實(shí)也可以做到,這里我個(gè)人習(xí)慣用窄表處理)。

        為了實(shí)現(xiàn)寬表變窄表,用到pandas里的melt方法。

        import?pandas?as?pd
        #?讀取下載后的數(shù)據(jù)
        df?=?pd.read_excel(r'F:\微信公眾號(hào)\matplotlib動(dòng)態(tài)圖\各地區(qū)生產(chǎn)總值.xlsx')
        df.head()
        #?使用melt方法進(jìn)行處理
        data?=?df.melt(id_vars='地區(qū)',value_vars=range(1993,2020),var_name='年份',value_name='生產(chǎn)總值(億)')
        data.head()

        4.matplotlib動(dòng)態(tài)可視化

        matplotlib動(dòng)態(tài)圖用到的是animation.FuncAnimation方法,其實(shí)動(dòng)態(tài)就是N張圖一張一張按照一定頻率刷新,我們也有其他方法實(shí)現(xiàn),這里不展開。

        在我們的效果展示中,可以看到 類型是條形圖,數(shù)值高低排序,每個(gè)條形圖顏色不一樣,我們來一步一步看看如何做出最終效果~

        4.1.樸實(shí)無華的條形圖

        barh是條形圖,就是橫著的柱狀圖,以下我們先取2019年的年度數(shù)據(jù)展示前10地區(qū)

        import?matplotlib.pyplot?as?plt
        import?matplotlib.ticker?as?ticker
        #?以下代碼解決顯示中文問題
        plt.rcParams['font.sans-serif']?=?['SimHei']
        #?繪制?2019年?各地區(qū)生產(chǎn)總值(前10)
        currentYear?=?2019
        ddata?=?(data[data['年份']==currentYear]
        ????????.sort_values(by='生產(chǎn)總值(億)',ascending?=?True)
        ????????.tail(10))
        fix,?ax?=?plt.subplots(figsize=(15,8))
        ax.barh(ddata['地區(qū)'],?ddata['生產(chǎn)總值(億)'])

        我們看到上面這張圖平平無奇,樸實(shí)無華的配色,沒有多一分的元素(標(biāo)題、數(shù)據(jù)標(biāo)簽等等),接下來我們先把條形圖美化一下

        4.2.有點(diǎn)還行的條形圖

        通過自定義條形圖配色,再附上一些text說明。

        關(guān)于配色,直接從網(wǎng)上(https://www.beejson.com/word/rgb.html)找 16進(jìn)制配色表,然后取31個(gè)即可(咱們一共有31個(gè)地區(qū)數(shù)據(jù)不含港澳臺(tái))。然后將31個(gè)地區(qū)與31個(gè)顏色進(jìn)行組合成字典備用!

        「構(gòu)造地區(qū)-顏色字典」

        #?我直接從網(wǎng)上批量復(fù)制了?30多個(gè)顏色值,然后隨機(jī)抽取31個(gè)和31個(gè)地區(qū)配對(duì)
        a?=?['#FFFFCC??#FFCC00??#CC9909??#663300??#FF6600??#663333??#CC6666??#FF6666??#FF0000??#FFFF99??#FFCC66??#FF9900??#FF9966??#CC3300??#996666??#FFCCCC??#660000??#FF3300??#FF6666??#FFCC33??#CC6600??#FF6633??#996633??#CC9999??#FF3333??#990000??#CC9966??#FFFF33??#CC9933??#993300??#FF9933??#330000??#993333??#CC3333??#CC0000??#FFCC99??#FFFF00??#996600']
        b?='?'.join(a)
        c?=?b.split('?\t')

        import?random
        #?隨機(jī)不放回抽取31個(gè)
        color?=?random.sample(c,31)
        #?獲取原數(shù)據(jù)中地區(qū)列表
        province?=?list(data['地區(qū)'].unique())
        #?組合成?地區(qū)-顏色值?字典
        colors?=?dict(zip(province,color))

        「繪制有顏的條形圖」

        fig,?ax?=?plt.subplots(figsize=(15,8))
        ax.barh(ddata['地區(qū)'],?ddata['生產(chǎn)總值(億)'],color?=?[colors[x]?for?x?in?ddata['地區(qū)']])
        #?在每個(gè)條形圖末端顯示?歸屬地區(qū)?及?生產(chǎn)總值(億)
        for?i,?(num,?pro)?in?enumerate(zip(ddata['生產(chǎn)總值(億)'],?ddata['地區(qū)'])):
        ????ax.text(num,i,?pro,?ha?=?'right')
        ????ax.text(num,i,?f':{num}億',?ha?=?'left')
        #?在右側(cè)中部偏下顯示當(dāng)前年份
        ax.text(1,?0.4,?currentYear,?transform=?ax.transAxes,?size=40,?ha='right')
        Text(1,?0.4,?'2019')

        有人就要說了,上面這個(gè)圖也沒啥好看的,除了增加了單獨(dú)的配色以及數(shù)據(jù)顯示外。。講的太對(duì)了,字體還丑、顏色搭配也是難看,當(dāng)然這些都是可以自己配置的 因?yàn)楹罄m(xù) 我們會(huì)換個(gè)plt.xkcd()**「手繪卡通風(fēng)格」**的形式,但是卡通風(fēng)格的形式需要特別處理中文字體顯示問題,這里先介紹下來自好朋友 「'小明哥'」 的幫助,如下代碼(設(shè)置字體為我系統(tǒng)里的微軟雅黑,字號(hào)16)

        #?字體管理
        from?matplotlib?import?font_manager
        my_font?=?font_manager.FontProperties(fname=r"C:\Windows\Fonts\msyh.ttc",size=14)
        #?再加入其他一些元素(如標(biāo)題、刻度線、刻度放在最上方等)
        fig,?ax?=?plt.subplots(figsize=(15,8))
        ax.barh(ddata['地區(qū)'],?ddata['生產(chǎn)總值(億)'],color?=?[colors[x]?for?x?in?ddata['地區(qū)']])

        for?i,?(num,?pro)?in?enumerate(zip(ddata['生產(chǎn)總值(億)'],?ddata['地區(qū)'])):
        ????ax.text(num,i,?pro,?ha?=?'right',fontproperties=my_font)
        ????ax.text(num,i,?f'?:{num}億',?ha?=?'left',fontproperties=my_font)

        ax.text(1,?0.4,?currentYear,?transform=?ax.transAxes,fontproperties=my_font,?size=40,?ha='right')

        #?x刻度設(shè)置在頂部
        ax.xaxis.set_ticks_position('top')
        #?x刻度顏色設(shè)置為灰色,大小為12
        ax.tick_params(axis=?'x',colors=?'#777777',labelsize=?12)
        #?去掉y刻度
        ax.set_yticks([])
        #?設(shè)置?xy軸內(nèi)邊距
        ax.margins(0,?0.01)
        #?顯示網(wǎng)格(x軸向虛線)
        ax.grid(which=?'major',?axis=?'x',linestyle=?'--')
        #?網(wǎng)格線至于底部
        ax.set_axisbelow(True)
        #?在左上角顯示?標(biāo)題(不是用的title方法)
        ax.text(0,?1.06,'全國各地區(qū)生產(chǎn)總值(1993-2019)',transform=?ax.transAxes,weight?=600,ha?=?'left',fontproperties=?my_font,size=24)
        #?去掉邊框
        plt.box(False)

        4.3.會(huì)動(dòng)的條形圖

        既然動(dòng)圖是一張張圖刷新而來,那我們把每年的數(shù)據(jù)都做一張圖再定時(shí)刷新替換不就好了,這樣當(dāng)然是可以的。

        所以,我們先看看「animation.FuncAnimation」(https://matplotlib.org/api/animation_api.html)吧

        官網(wǎng)有個(gè)簡單的例子:sin(x)的動(dòng)態(tài)演示。這里不做介紹,源碼清晰,我們直接現(xiàn)學(xué)現(xiàn)做~

        先把上面作圖代碼封裝成函數(shù)

        這個(gè)函數(shù)只需要一個(gè)參數(shù),year(年份)

        fig,?ax?=?plt.subplots(figsize=(12,16))
        def?drawBarh(year):
        ????ddata?=?(data[data['年份']==year]
        ????????.sort_values(by='生產(chǎn)總值(億)',ascending?=?True)
        ????????.tail(31))
        ????ax.clear()
        ????
        ????ax.barh(ddata['地區(qū)'],?ddata['生產(chǎn)總值(億)'],color?=?[colors[x]?for?x?in?ddata['地區(qū)']])

        ????for?i,?(num,?pro)?in?enumerate(zip(ddata['生產(chǎn)總值(億)'],?ddata['地區(qū)'])):
        ????????ax.text(num,i,?pro,?ha?=?'right',fontproperties=my_font)
        ????????ax.text(num,i,?f'?:{num}億',?ha?=?'left',fontproperties=my_font)

        ????ax.text(1,?0.4,?year,?transform=?ax.transAxes,fontproperties=my_font,?size=40,?ha='right')

        ????#?x刻度設(shè)置在頂部
        ????ax.xaxis.set_ticks_position('top')
        ????#?x刻度顏色設(shè)置為灰色,大小為12
        ????ax.tick_params(axis=?'x',colors=?'#777777',labelsize=?12)
        ????#?去掉y刻度
        ????ax.set_yticks([])
        ????#?設(shè)置?xy軸內(nèi)邊距
        ????ax.margins(0,?0.01)
        ????#?顯示網(wǎng)格(x軸向虛線)
        ????ax.grid(which=?'major',?axis=?'x',linestyle=?'--')
        ????#?網(wǎng)格線至于底部
        ????ax.set_axisbelow(True)
        ????#?在左上角顯示?標(biāo)題(不是用的title方法)
        ????ax.text(0,?1.06,'全國各地區(qū)生產(chǎn)總值(1993-2019)',transform=?ax.transAxes,weight?=600,ha?=?'left',fontproperties=?my_font,size=24)
        ????#?去掉邊框
        ????plt.box(False)

        #?演示2019年數(shù)據(jù)
        drawBarh(2019)

        animation動(dòng)圖制作

        再調(diào)用animation.FuncAnimation方法進(jìn)行動(dòng)圖制作,我們?cè)谳敵龅捻撁婵梢赃M(jìn)行動(dòng)畫演示(快捷、后退、開始、暫停等等)。

        fig?,ax?=plt.subplots(figsize?=?(12,16))
        #?手繪卡通風(fēng)格
        plt.xkcd()
        animator?=?animation.FuncAnimation(fig,drawBarh,frames=range(1993,2020),interval=500)
        HTML(animator.to_jshtml())
        #?通過以下方式可以保存為動(dòng)圖(保存為視頻方式我們單獨(dú)介紹吧)
        animator.save('生產(chǎn)總值動(dòng)態(tài)圖.gif',bitrate=1800,writer?='pillow')
        ?

        「交流與思考」:我們?cè)谛Ч麆?dòng)圖中發(fā)現(xiàn)其實(shí)沒那么順滑,這是因?yàn)槲覀兪前凑彰恳荒甑臄?shù)據(jù)繪制一次導(dǎo)致的,那么如何讓效果更加順滑呢?

        (一般來說,可以把每年的數(shù)據(jù)分為多份,比如我們認(rèn)為每兩年之間存在N組值,那么就是有N-2個(gè)缺失值,通過pandas的缺失值插值處理可以補(bǔ)充一些值作為繪圖的輔助值,從而讓效果更加順滑,那么如何進(jìn)行插值呢?pandas其實(shí)有現(xiàn)成的方式,這里也不展開說明了)

        ?

        -END-



        瀏覽 60
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            3d啪啪动漫精品少妇 | 18禁网站在线免费观看 | 狠狠色噜噜色狠狠狠综合久久成人 | 日韩精品AV无码一区二区三区 | 国产又猛又黄又爽 | 嗯嗯h视频 | 国产超黄视频 | 日日夜夜做爱 | 色偷偷色噜噜狠狠成人免费视频 | 国产高清区 |