第二章 斑駁陸離的調色板
顏色顯然比圖形風格的其他方面都更加重要,因為顏色使用得當就可以有效顯示或隱藏數據中的特征。有許多的好資源都可以了解關于在可視化中使用顏色的技巧,推薦Rob Simmon的《series of blog posts》和這篇進階的技術文章,matplotlib文檔現在也有一個很好的教程,說明了如何在內置色彩映射中構建的一些感知特性。
Seaborn讓你更容易選擇和使用那些適合你數據和視覺的顏色。
%matplotlib inline
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(rc={"figure.figsize": (6, 6)})
np.random.seed(sum(map(ord, "palettes")))
通過color_palette()創建調色板
最重要的直接設置調色板的函數就是color_palette()。這個函數提供了許多(并非所有)在seaborn內生成顏色的方式。并且它可以用于任何函數內部的palette參數設置(在某些情況下當需要多種顏色時也可以傳入到color參數)
color_palette()允許任意的seaborn調色板或matplotlib的顏色映射(除了jet,你應該完全不使用它)。它還可以使用任何有效的matplotlib格式指定的顏色列表(RGB元組、十六進制顏色代碼或HTML顏色名稱)。返回值總是一個RGB元組的列表。
最后,直接調用沒有傳入參數的color_palette()將返回默認的顏色循環。
對應的函數set_palette()接受相同的參數,并為所有圖設置默認的顏色循環。你也可以在with塊中使用color_palette()來實現臨時的更改調色板配置(下面有詳細例子)。
通常在不知道數據的具體特征的情況下不可能知道什么類型的調色板或顏色映射對于一組數據來說是最好的。因此,我們將用三種不同類型的調色板:分類色板、連續色板和離散色板,來區分和使用color_palette()函數。
分類色板
分類色板(定性)是在區分沒有固定順序的數據時最好的選擇。
在導入seaborn庫后,默認的顏色循環被更改為一組六種顏色。雖然這些顏色可能會讓你想起matplotlib的標準顏色循環,但他們無疑更賞心悅目一些。
current_palette = sns.color_palette()
sns.palplot(current_palette)
默認顏色主題共有六種不同的變化分別是:deep, muted, pastel, bright, dark, 和 colorblind。類似下面的方式直接傳入即可。
current_palette = sns.color_palette("dark") # 直接傳入對應的參數即可變化
sns.palplot(current_palette)
使用圓形顏色系統
當你有六個以上的分類要區分時,最簡單的方法就是在一個圓形的顏色空間中畫出均勻間隔的顏色(這樣的色調會保持亮度和飽和度不變)。這是大多數的當他們需要使用比當前默認顏色循環中設置的顏色更多時的默認方案。
最常用的方法是使用hls的顏色空間,這是RGB值的一個簡單轉換。
sns.palplot(sns.color_palette("hls", 8))
當然,也可以使用hls_palette()函數來控制顏色的亮度和飽和。
sns.palplot(sns.hls_palette(8, l=.3, s=.8))
# l-亮度 lightness / s-飽和 saturation
由于人類視覺系統的工作方式,會導致在RGB度量上強度一致的顏色在視覺中并不平衡。比如,我們黃色和綠色是相對較亮的顏色,而藍色則相對較暗,使得這可能會成為與hls系統一致的一個問題。
為了解決這一問題,seaborn為husl系統提供了一個接口,這也使得選擇均勻間隔的色彩變得更加容易,同時保持亮度和飽和度更加一致。
sns.palplot(sns.color_palette("husl", 8))
使用分類顏色調色板
另一種視覺上令人愉悅的分類調色板來自于Color Brewer工具(它也有連續調色板和離散調色板,我們將在下面的圖中看到)。這些也存在于matplotlib顏色映射中,但是它們沒有得到適當的處理。在這里,當你要求一個定性顏色的調色板時,你總是會得到離散的顏色,但這意味著在某一點它們會開始循環。
Color Brewer工具的一個很好的特點是,它提供了一些關于調色板是色盲安全的指導。有各種各樣的適合色盲的顏色,但是最常見的變異導致很難區分紅色和綠色。一般來說,避免使用紅色和綠色來表示顏色以區分元素是一個不錯的主意。
sns.palplot(sns.color_palette("Paired"))
sns.palplot(sns.color_palette("Set2", 10))
為了幫助您從Color Brewer工具中選擇調色板,這里有choose_colorbrewer_palette()函數。這個函數必須在IPython notebook中使用,它將啟動一個交互式小部件,讓您瀏覽各種選項并調整參數。
當然,您可能只想使用一組您特別喜歡的顏色。因為color_palette()接受一個顏色列表,這很容易做到。
flatui = ["#9b59b6", "#3498db", "#95a5a6", "#e74c3c", "#34495e", "#2ecc71"]
sns.palplot(sns.color_palette(flatui))
sns.choose_colorbrewer_palette("sequential")
# data_type: {‘sequential’, ‘diverging’, ‘qualitative’}
sns.choose_colorbrewer_palette("sequential",as_cmap=True)
# as_cmap參數用來更改顯示的顏色范圍是離散的還是連續的
使用xkcd顏色來命名顏色
xkcd包含了一套眾包努力的針對隨機RGB色的命名。產生了954個可以隨時通過xdcd_rgb字典中調用的命名顏色。
plt.plot([0, 1], [0, 1], sns.xkcd_rgb["pale red"], lw=3)
plt.plot([0, 1], [0, 2], sns.xkcd_rgb["medium green"], lw=3)
plt.plot([0, 1], [0, 3], sns.xkcd_rgb["denim blue"], lw=3);
如果你想花一些時間挑選顏色,或許這種交互式的可視化(官方鏈接失效)是非常有幫助的。除了將單一顏色從xkcd_rgb字典中取出,也可以通過名稱列表傳入xkcd_palette()函數中取得顏色組。
colors = ["windows blue", "amber", "greyish", "faded green", "dusty purple"]
sns.palplot(sns.xkcd_palette(colors))
連續色板
調色板中第二大類稱為“順序”。這種顏色映射對應的是從相對低價值(無意義)數據到高價值(有意義)的數據范圍。雖然有時候你會需要一個連續的離散顏色調色板,用他們像kdeplot()或者corrplot()功能映射更加常見(以及可能類似的matplotlib功能)。
非常可能的是見到jet色彩映射(或其他采用調色板)在這種情況下使用,因為色彩范圍提供有關數據的附加信息。然而,打的色調變化中往往會引入不連續性中不存在的數據和視覺系統不能自然的通過“彩虹色”定量產生“高”、“低”之分。其結果是,這樣的可視化更像是一個謎題,模糊了數據中的信息而并非揭示這種信息。事實上,jet調色板可能非常糟糕,因為最亮的顏色,黃色和青色用于顯示中間數值,這就導致強調了一些沒有意義的數據而忽視了端點的數據。
所以對于連續的數據,最好是使用那些在色調上相對細微變化的調色板,同時在亮度和飽和度上有很大的變化。這種方法將自然地吸引數據中相對重要的部分
Color Brewer的字典中就有一組很好的調色板。它們是以在調色板中的主導顏色(或顏色)命名的。
sns.palplot(sns.color_palette("Blues"))
就像在matplotlib中一樣,如果您想要翻轉漸變,您可以在面板名稱中添加一個_r后綴。
sns.palplot(sns.color_palette("BuGn_r"))
seaborn還增加了一個允許創建沒有動態范圍的"dark"面板。如果你想按順序畫線或點,這可能是有用的,因為顏色鮮艷的線可能很難區分。
類似的,這種暗處理的顏色,需要在面板名稱中添加一個_d后綴
sns.palplot(sns.color_palette("GnBu_d"))
牢記,你可能想使用choose_colorbrewer_palette()函數取繪制各種不同的選項。如果你想返回一個變量當做顏色映射傳入seaborn或matplotlib的函數中,可以設置as_cmap參數為True。
cubehelix_palette()函數的連續調色板
cubehelix調色板系統具有線性增加或降低亮度和色調變化順序的調色板。這意味著在你的映射信息會在保存為黑色和白色(為印刷)時或被一個色盲的人瀏覽時可以得以保留。
Matplotlib擁有一個默認的內置cubehelix版本可供創建:
sns.palplot(sns.color_palette("cubehelix", 8))
seaborn為cubehelix系統添加一個接口使得其可以在各種變化中都保持良好的亮度線性梯度。
通過seaborn的cubehelix_palette()函數返回的調色板與matplotlib默認值稍有所不同,它不會在色輪周圍旋轉或覆蓋更廣的強度范圍。seaborn還改變了排序使得更重要的值顯得更暗:
sns.palplot(sns.cubehelix_palette(8))
其他cubehelix_palette()的參數主要調整色板的視覺。兩個重要的選擇是:start(值的范圍為03)和rot,還有rot的次數(-11之間的任意值)
sns.palplot(sns.cubehelix_palette(8, start=.5, rot=-.75))
你也可以控制斷點的亮度和甚至對調結果順序
sns.palplot(sns.cubehelix_palette(8, start=2, rot=0, dark=0, light=.95, reverse=True))
默認情況下你只會得到一些與seaborn調色板相似的顏色的列表,但你也可以讓調色板返回一個可以用as_cmap=True傳入seaborn或matplotlib函數的顏色映射對象
x, y = np.random.multivariate_normal([0, 0], [[1, -.5], [-.5, 1]], size=300).T
cmap = sns.cubehelix_palette(light=1, as_cmap=True)
sns.kdeplot(x, y, cmap=cmap, shade=True);
類似的,也可以在notebook中使用choose_cubehelix_palette()函數啟動一個互助程序來幫助選擇更適合的調色板或顏色映射。如果想讓函數返回一個類似hexbin的顏色映射而非一個列表則需要傳入as_cmap=True。
使用light_palette() 和dark_palette()調用定制連續調色板
這里還有一個更簡單的連續調色板的使用方式,就是調用light_palette() 和dark_palette(),這與一個單一顏色和種子產生的從亮到暗的飽和度的調色板。這些函數還伴有choose_light_palette() and choose_dark_palette()函數,這些函數啟動了交互式小部件來創建這些調色板。
sns.palplot(sns.light_palette("green"))
sns.palplot(sns.dark_palette("purple"))
這些調色板結果也可以顛倒
sns.palplot(sns.light_palette("navy", reverse=True))
當然也可以創建一個顏色映射對象取代顏色列表
pal = sns.dark_palette("palegreen", as_cmap=True)
sns.kdeplot(x, y, cmap=pal);
默認情況下,任何有效的matplotlib顏色可以傳遞給input參數。也可以在hls或husl空間中提供默認的rgb元組,您還可以使用任何有效的xkcd顏色的種子。
sns.palplot(sns.light_palette((210, 90, 60), input="husl"))
sns.palplot(sns.dark_palette("muted purple", input="xkcd"))
需要注意的是,為默認的input空間提供交互的組件是husl,這與函數自身默認的并不同,但這在背景下卻是更有用的。
離散色板
調色板中的第三類被稱為“離散”。用于可能無論大的低的值和大的高的值都非常重要的數據。數據中通常有一個定義良好的中點。例如,如果你正在繪制溫度變化從基線值,最好使用不同色圖顯示相對降低和相對增加面積的地區。
選擇離散色板的規則類似于順序色板,除了你想滿足一個強調的顏色中點以及用不同起始顏色的兩個相對微妙的變化。同樣重要的是,起始值的亮度和飽和度是相同的。
同樣重要的是要強調,應該避免使用紅色和綠色,因為大量的潛在觀眾將無法分辨它們。
你不應該感到驚訝的是,Color Brewer顏色字典里擁有一套精心挑選的離散顏色映射:
sns.palplot(sns.color_palette("BrBG", 7))
sns.palplot(sns.color_palette("RdBu_r", 7))
另一個在matplotlib中建立的明智的選擇是coolwarm面板。請注意,這個顏色映射在中間值和極端之間并沒有太大的對比。
sns.palplot(sns.color_palette("coolwarm", 7))
用diverging_palette()使用定制離散色板
你也可以使用海運功能diverging_palette()為離散的數據創建一個定制的顏色映射。(當然也有一個類似配套的互動工具:choose_diverging_palette())。該函數使用husl顏色系統的離散色板。你需隨意傳遞兩種顏色,并設定明度和飽和度的端點。函數將使用husl的端點值及由此產生的中間值進行均衡。
sns.palplot(sns.diverging_palette(220, 20, n=7))
sns.palplot(sns.diverging_palette(145, 280, s=85, l=25, n=7))
sep參數控制面板中間區域的兩個漸變的寬度。
sns.palplot(sns.diverging_palette(10, 220, sep=80, n=7))
也可以用中間的色調來選擇調色,而不是用亮度
sns.palplot(sns.diverging_palette(255, 133, l=60, n=7, center="dark"))
用set_palette()更改色變的默認值
color_palette() 函數有一個名為set_palette()的配套。它們之間的關系類似于在美學教程中涉及的aesthetics tutorial. set_palette()。set_palette()接受與color_palette()相同的參數,但是它會更改默認的matplotlib參數,以便成為所有的調色板配置。
def sinplot(flip=1):
x = np.linspace(0, 14, 100)
for i in range(1, 7):
plt.plot(x, np.sin(x + i * .5) * (7 - i) * flip)
sns.set_palette("husl")
sinplot()
color_palette()函數也可以在一個with塊中使用,以達到臨時更改調色板的目的
with sns.color_palette("PuBuGn_d"):
sinplot()
簡單常用色彩總結:
- 分類:hls husl Paired Set1~Set3(色調不同)
- 連續:Blues[藍s,顏色+s] BuGn[藍綠] cubehelix(同色系漸變)
- 離散:BrBG[棕綠] RdBu[紅藍] coolwarm[冷暖](雙色對稱)
本章后記
這章內容確認讓對色彩與不同數據形式的圖像之間的關系有了新的認識,恐怕色讓圖形好看和更有格調僅僅只是初級階段。然而文中涉及了大量的色彩專用的名詞和理論,只能不求甚解的翻出來強行理解了,謬誤在所難免,歡迎各位大神指正,萬分感謝!