最近本人接到一個實驗室大師姐的小任務,就是畫一個HeatMap,也就是熱圖啦。本來是一件非常簡單的事情。於是我用seaborn庫的heatmap函數畫了一張如下的圖
當然,這張圖是假的。這麼重要的數據怎麼能真的發出來呢。
但是這張這麼好看的圖居然被拒了。What?! 原因是一般用從藍到紅的冷暖表示少到多嘛。那好吧,我又給了如下這些圖。
當然,右下角的騷藍和騷紫是隔壁老王建議的。畫出來他自己都拒絕。
其實有沒有人覺得已經挺好看的了?這個是官方演示圖啦,它數據是漸變的,啥都好看。要是數據基本不是漸變的呢?
還好看麼?
那首先介紹一下上面這些圖是怎麼畫出來的吧。
1 2 3 4 5 6 7 8 9 |
import seaborn as sns import numpy as np import matplotlib.pylab as plt flights = sns.load_dataset("flights") flights = flights.pivot("month", "year", "passengers") ax = sns.heatmap(flights, cmap="cool") plt.show() |
好吧,這就是很簡單的官網給的例程。詳情可以看看:http://seaborn.pydata.org/generated/seaborn.heatmap.html
相信看完你也能畫出上面的圖,需要修改的只是heatmap(cmap=?)里面的cmap参数而已。那么这个参数的可选值去哪里找呢?这种时候就是要去看官网。
最重要的一句話matplotlib colormap name or object, or list of colors, optional
它並沒有告訴妳cmap能取什麽值,但是它說了它能支持所有matplotlib庫定義的colormap。好了,這個時候我們知道應該要去找matplotlib的文檔了,詳情請見Colormap reference: https://matplotlib.org/gallery/color/colormap_reference.html
下面是其中一小部分。左邊都有colormap的名字,只要寫到cmap參數裡面就可以了。就是那麼簡單。
好吧,講到這裡都還沒有講到重點。!!!重點來了!!!重點就是你不想要這裡面的colormap怎麼辦!!!
為什麼我會提出這樣神奇的問題,就是因為我幾乎把這裡面的colormap畫遍了,大師姐都面露難色,額…其實畫的圖好看不好看不完全是colormap的問題,有很大程度上也是因為數據的分布…這就像是,一幅畫,顏色用得好也不行啊,也得看你東西畫得怎麼樣不是?反過來思考一下,已經有了要畫得東西,你怎麼用色能讓它看上去更好看呢?
好吧,又扯遠了。我一介工科生,還是好好畫圖吧。
好了,能自製colormap么?人家說了呀,matplotlib colormap name or object, or list of colors, optional
所以明顯可以自己傳一個list進去作為colormap。稍微有點Python取色經驗的人都知道,Python裡面顏色都是用256RGB字符串表示的,比如”#FFFFFF”表示一個純白。這個時候可以查一下什麼RGB顏色對照表:https://www.114la.com/other/rgb.htm
如果你想更加優雅一點,那麼推薦一個Sublime的插件(什麼?你這麼剛好也是用Sublime?!)colorpicker。
那就不用查表,可以自己選顏色啦。
好了那選了顏色要怎麼變成colormap呢?colormap實際上就是一個漸變色的列表,只要選定兩個或者多個顏色,然後讓顏色從一個顏色慢慢變到另一個顏色去就好了。
那麼RGB三個值的調整,你是不是準備寫3個循環去做呢?又或者你看清了三個顏色分量是同步變化的,各自的步長算出來只需要1個循環即可?
那麼以下是我認為寫這個for循環非常優雅的方法——利用list裡面的for以及for可能用到的zip
1 2 3 4 5 6 7 8 |
start=0xF2F2F2 # From stop=0x0000EE # To num=100 # Divided into 100 steps color=["#{:02x}{:02x}{:02x}".format(x,y,z) for x,y,z in zip(\ np.round(np.linspace(start>>16,stop>>16,num)).astype(int),\ np.round(np.linspace((start>>8)&0xFF,(stop>>8)&0xFF,num)).astype(int),\ np.round(np.linspace(start&0xFF,stop&0xFF,num)).astype(int))] |
其實這樣就可以了。要理解color那一句,需要有一丟丟的基礎知識:
- [2*x for x in range(100)] 這種東西
- “Name: {}”.format(str) 這種format方式的字符串格式化
- zip()打包元組函數,將對象中對應的元素打包成一個個元組,然後以列表形式返回。
- np.round()取整函數,為什麼要取整?因為顏色都要是0~0xFF的整數
- np.linspace(start, stop, num)這個函數大家應該都不會陌生,就是把start到stop之間分成num份。
- ndarray.astype(int)轉換數據類型,否則儘管你取整了,那還是float類型,會報錯
- 左移右移去取對應位
下面講一下zip()的簡單用法
1 2 3 4 5 6 7 |
>>> a = [1,2,3] >>> b = [4,5,6] >>> c = [4,5,6,7,8] >>> zip(a,b) # 打包为元组的列表 [(1, 4), (2, 5), (3, 6)] >>> zip(a,c) # 元素个数与最短的列表一致 [(1, 4), (2, 5), (3, 6)] |
所以如果你想要在for循環裡面控制多個同步變化的變量不妨這樣:
別的就不說了。接著只需要把生成的colormap傳入到cmap就可以了。
同理,只要擴展一下就可以做到多個顏色之間的漸變colormap了。
於是男生們可以自製口紅色號圖鍛煉一下了
最后口红色好评!
另,动态背景+交互厉害了!
嘻嘻。动态的背景是个插件啦