本文示例代碼及文件已上傳至我的
Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes
1 簡介
我們在繪制某些地圖時,為了凸顯出每個獨立的區域,需要滿足拓撲着色要求,即所有相鄰的區域不可以用同一種顏色繪制,以前的手繪地圖需要繪制者自行思考設計具體的着色規則,而現如今通過計算機的輔助,我們可以快速生成大量的着色方案。
今天我們就來學習配合geopandas如何快速實現地圖的拓撲着色。
2 基於mapclassify的地圖拓撲着色
對於着色方案的生成,我們需要使用到mapclassify這個第三方庫,以前我的geopandas系列文章分層設色篇也介紹過其中的諸多功能,而本文需要使用到其特殊的greedy功能。
以中國縣級單元矢量邊界數據為例,它包含了共2900個縣級單元的行政區划面矢量要素:
對於這樣一個典型的面要素眾多的地圖,利用mapclassify.greedy(),我們可以基於面要素之間的鄰接拓撲關系,快速生成一定配色數量的方案出來,greedy()的主要參數如下:
- gdf:GeoDataFrame型,用於傳入待處理的地理數據框
- strategy:str型,用於設定拓撲着色所采取的具體策略,默認為
balanced(這也是QGIS中拓撲着色所使用的方法),其余可選策略有'largest_first'、'random_sequential'、'smallest_last'、'independent_set'、'connected_sequential_bfs'、'connected_sequential_dfs'、'connected_sequential'、'saturation_largest_first'、'DSATUR'等,詳細介紹見https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.coloring.greedy_color.html - balance:str型,當
strategy='balanced'時,用於設定如何進行“平衡”着色,默認為'count',可選項如下,其中除了'count'方式以外,其余方式均需要輸入的GeoDataFrame為投影坐標系:- count:盡量保持每種顏色對應的面要素數量平衡
- area:盡量保持每種顏色對應的面要素面積之和平衡
- centroid:盡量保持每種顏色對應的面要素之間重心距離平衡
- distance:盡量保持每種顏色對應的面要素之間拓撲距離平衡
- min_colors:int型,當
strategy='balanced'時,用於設置色彩方案至少的色彩數量,最后運算產生的色彩划分結果可能會大於這個參數 - sw:str型,用於設定拓撲鄰接關系判定策略,
'rook'表示共邊鄰接,'queen'表示共點鄰接,默認為'queen' - min_distance:數值型,默認為
None,有時由於數據質量、精度的原因,可能會導致肉眼看起來的鄰接實際上仍然存在一定的“間距”,這時就可以使用min_distance參數來設定距離閾值來幫助greedy捕捉相鄰面要素關系,即面要素兩兩之間拓撲距離小於min_distance時也視作“鄰接”
知曉了greedy()的主要參數后,我們下面來演示如何使用它來輔助制作拓撲着色地圖。
首先我們需要向greedy()中傳入對應的面要素GeoDataFrame,greedy()會根據我們的參數設定為每一個面生成一個標簽,我們只需要將此標簽列作為繪圖着色映射列即可,可以看到最終得到的標簽方案中共有7種不同標簽,雖然按照四色問題的猜想,任何拓撲着色地圖只需要4種顏色即可完成色彩填充,但在有限的計算時間內,greedy()給出了還不錯的方案:
按照標簽進行顏色分配:
放大仔細發現,每個鄰接的區域的確實現了顏色不重合:
而如果你希望用自定義色彩值來配合標簽字段進行映射,則可以參考我下面的做法,將具體的顏色值譬如16進制色彩字符串傳入color參數,這里使用到以前介紹過多次的配色庫palettable:
以上就是本文的全部內容,歡迎在評論區與我進行討論~
