做地图这件事,单变量看到头,双变量才是真正开始纠结的地方。比如人口密度和家庭收入、污染浓度和呼吸道疾病、房价和租金,这类“一个空间里两个指标同时变化”的问题,画两张图并排看总觉得差点意思,眼睛来回扫半天也说不清“到底哪里两个指标都高、哪里一个高一个低”。QGIS里有一种很成熟的呈现方式叫二元分区着色图,能把两个变量同时塞进一张地图的色调关系里,一眼看出空间分布上的组合类型。这篇文章我就从原理、数据准备、实操步骤到避坑经验,完整拆一遍这个技巧,适合正在做区域分析、城市规划、商业选址、社会经济数据可视化的朋友参考。
需要说明的是,这里用的方法是“双图层叠加 + 混合模式”方案,之所以这么选,是因为QGIS默认的符号系统没有一键生成二维分类图的按钮,但通过巧妙的图层叠加,效果完全不输专业商业软件,而且自由度更高。
1. 内容整体设计与思路拆解
1.1 为什么需要“二元分区着色图”
先想一个问题:如果手里有两个变量,想同时展示在地图上,最常见的做法是什么?
大多数人第一反应是画两幅图并排,左边是变量A,右边是变量B。但人眼的视觉对比能力远没有我们想象的强,尤其是当图幅较大、图例不同、色带不一致时,读者很难在脑子里完成“叠加比较”这一步。你真正想表达的往往是“高A高B”“高A低B”“低A高B”“低A低B”这四种组合,并排看图等于把判断工作全部抛给了读者。
二元分区着色图解决的就是这个核心矛盾:用颜色本身携带“两个维度的信息”。它的基本逻辑其实很简单——把两个变量分别映射到两种基础色相上,比如变量A用暖色渐深表示“越来越高”,变量B用冷色渐深表示“越来越高”,然后把两张图叠在一起。暖色和冷色混合后会形成一系列新的颜色:哪边都高就是深紫色系,哪边都低就是浅灰色系,只有A高是暖色系,只有B高是冷色系。
这种思路在统计学上很像“二维核密度”的可视化简化版本,在地理学里则被叫作bivariate choropleth map,很多政府统计部门和研究机构都爱用这个方案展示收入与教育水平、健康状况与医疗资源之间的关系。
1.2 为什么不用其他可视化方案
在自己动手之前,我建议你先把这个方案的适用边界搞清楚,否则做出来很容易被质疑“花哨但信息量不足”。我列几个常见替代方案,逐个说明它们的利弊。
| 方案 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 并排两幅单变量地图 | 实现简单,读者熟悉 | 视觉对比困难,空间组合关系无法一眼看出 | 两个变量各自分布规律都重要、不需要看组合关系时 |
| 散点图 + 地图联动 | 能精确看出相关性 | 地图和散点图要来回切换,交互实现成本高 | 有交互条件的线上分析平台 |
| 二元分区着色图 | 一张图容纳两个变量,组合关系一目了然 | 颜色解读需要训练,图例设计较麻烦 | 静态报告、海报、规划方案展示 |
| 小倍数(small multiples) | 信息密度高,适合展示更多维度 | 幅面占用大,读者对比较吃力 | 3个以上变量、需要严谨对比时 |
从这个表能看出来,二元分区着色图并不是“万能药”,它赢在“空间组合关系”的表达效率上。如果你手里两个变量之间基本不相关,或者你更关心单个变量的高值区域,那老老实实画两幅单变量图反而更靠谱。
1.3 工具选型:为什么是QGIS
市面上能做二元分区着色的工具有不少。ArcGIS Pro 通过Arcade表达式也能模拟,但操作路径相对繁琐;Datawrapper这类在线工具有现成的bivariate模板,缺点是数据得传到云端、图层精细控制能力弱;R语言和Python也能做,但对非编程背景的同事太不友好。
QGIS最打动我的是三点:一是完全免费开源,团队协作时不用担心授权问题;二是符号系统足够灵活,同一个图层复制两份、分别用不同方式渲染、再用混合模式叠加,这个能力比很多商业软件还顺手;三是中文资料近年来逐渐多了起来,新用户在渲染设置里把界面语言切到简体中文,学习门槛会降一大截。
把同一份矢量数据复制出两个图层,分别赋予热色系和冷色系渐变,再通过“乘法/正片叠底”混合模式叠加,这本质上是在利用RGB颜色空间里的通道混合逻辑——具体怎么做,第三章会详细展开。
2. 数据准备:决定成图效果的隐藏工程量
2.1 属性表怎么组织最省心
很多人一上来就急着打开符号系统配色,做完才发现颜色全乱了,回头排查半天,根源往往是数据表结构没理清。做二元分区着色之前,先把矢量图层的属性表打开,确认两列关键字段的格式是数值型,而不是文本型。QGIS里文本型字段显示为右对齐,数值型字段显示为左对齐,这一眼就能分出来。
如果手头数据没有现成的两列数值,就得先做字段计算。比如你手里是某市的街道边界,带总人口和总面积两列,那“人口密度”就可以通过字段计算器新建一列来算。操作路径是:右键图层 → 打开属性表 → 左上角“字段计算器”按钮 → 勾选“新建字段”→ 输出字段名填“pop_density”→ 表达式写"total_pop" / "area_km2",精度选整数或双精度都行。
建议把所有参与计算的中间字段都显式建出来,别在符号系统表达式里临时算。临时计算很容易在后期调整阈值时找不到入口,字段写死之后,每次只需刷新数值,符号系统自动联动,效率高得多。
2.2 归一化:直接上色等于给自己埋雷
这是二元分区着色里最容易被忽视、却最容易翻车的环节。
两个变量如果量纲不同,比如一个取值范围是0到100,另一个是0到100000,直接扔进符号系统做渐变,结果必然是数值大的那个变量“压过”另一个,整张图的颜色几乎只反映大数量级的变量。所以在进入渲染之前,必须让两个变量要么都变成比率(如密度、百分比、人均值),要么都做归一化处理。
归一化最朴素的做法就是极差标准化,把每个变量的取值映射到0到1之间。在QGIS字段计算器里写表达式也很简单,比如全局最小值和最大值可以用minimum("字段名")和maximum("字段名")直接取到,新建一列写("x" - minimum("x")) / (maximum("x") - minimum("x"))即可。这个方法的好处是成图颜色对比鲜明,坏处是离群值会把大多数区域压到很低的色阶上,所以做之前最好先看一下直方图分布。
另一种更稳健的思路是排名百分位,简单说就是每个要素的排序百分比代替原始数值。这种变换在统计里叫分位数变换,对偏态分布特别友好。如果你没有装额外插件,可以在字段计算器里用percent_rank("x")函数,QGIS从3.x版本开始内置了相关统计函数,非常方便。
2.3 分类方法与阈值选择
把两个变量都处理成连续渐变值之后,紧接着要决定怎么切分类。这里的“分类阈值”直接决定了读者看到的是“细腻渐变”还是“清晰的四象限色块”。
| 分类方法 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 分位数法(Quantile) | 每个类别包含相等数量的要素 | 各类别均匀,图面平衡 | 可能把相近值强行切开 | 分布偏态严重时首选 |
| 等间隔法(Equal Interval) | 按数值范围平均切分 | 阈值好解释,间距清晰 | 极端值会吞噬中间类别 | 数据近似均匀分布时 |
| 标准差法(Standard Deviation) | 按距均值几个标准差切分 | 便于识别离群区域 | 普通读者不太理解 | 数据接近正态分布时 |
我的经验是:做二元分区图的初期阶段,直接选“分位数法”,分成3段或4段都行。分位数法能保证每个阈值区间内的要素数量相对均衡,避免某个变量高值区只有零星几个面,结果成图后四象限颜色分布失衡。等你把整体流程跑通、对颜色组合有了感觉,再回头试试其他方法也不迟。
顺带提醒一个细节:符号系统里的分类数如果设置成“4×4”矩阵(即每个变量分4段),成图理论上有16种颜色组合,信息量一下子大了很多,但图例和读者的认知负担会爆炸。第一次做,控制在3×3九宫格以内,四象限的解读效率反而更高。
3. 五步做出第一张属于你的二元着色图
3.1 同一份数据,复制成两个图层
数据准备妥当之后,进入QGIS正式开始制图。第一步很无脑但很关键:在图层面板里右键你的矢量图层,选择“复制图层”,然后“粘贴图层”,会得到一个一模一样的副本。把副本重命名成类似“变量A_暖色层”“变量B_冷色层”,避免后期叠加时搞混。
为什么要两份图层?因为QGIS的符号化系统一个图层只能有一套颜色方案。二元着色图需要两个变量的色带在同一个图面上混合,最直接的办法就是让它们分别占据两个独立图层,利用图层叠加来“混合颜色”。
这里有一个认知要把牢:这两个图层用的是完全相同的几何数据,区别只在于渲染方式。后期调整时,你改了其中一个图层的符号样式,不会影响另一个,这正是我们想要的解耦效果。
3.2 第一层:用暖色渐变表达变量A
先把“变量A_暖色层”设为可见,把“变量B_冷色层”暂时关掉,我们从最底层的那个变量开始。
右键图层 → 属性 → 符号化,在“符号化”下拉框里选“渐变”或“分级”。如果选渐变,色带直接选从浅黄到橙红这类暖色序列;如果选“分级”,同步设置分类方法和分类数。我一般习惯把阈值切好后再去调整配色,操作路径是:符号化选项卡里选择“分级”,模式选择“分位数”,类别填3,然后双击每个类别前面的颜色块,单独调整颜色。
底层的颜色建议从“很浅的米黄色”到“中等橙黄色”再到“深橙红色”。注意最浅颜色不要太白,后面还要叠加第二层,太浅的底色可能会被上层颜色完全盖住。
3.3 第二层:用冷色渐变表达变量B
现在打开“变量B_冷色层”的符号化设置,同样选择“渐变”或“分级”,这次用冷色系:浅蓝、中蓝、深蓝。
关键一步来了:在“符号化”对话框下方找到“图层渲染”或“符号渲染”区,里面有“混合模式”选项。把混合模式从默认的“正常”改为“乘法”(Multiply)。有些版本的QGIS里也叫“正片叠底”,本质是一样的。
混合模式选“乘法”后,不光要保证两个图层几何重合,还要让它们颜色按通道相乘。假设底层是橙红色(R=200, G=50, B=0),上层是蓝色(R=0, G=50, B=200),乘法混合就是每个通道对应相乘之后除以255,得到的是一个偏深色的蓝紫色。这就是“高A高B”区域会呈现深色系的原因——两个颜色都在强饱和状态,相乘后亮度被压低,而“低A低B”区域因为两边都接近浅色,相乘后依然很浅。
那为什么不直接用“透明度”叠加?透明度叠加本质是加权求和,两个强色叠在一起颜色会变灰变脏,而且方向感不清晰。乘法混合保留了两个色相各自的“存在痕迹”,更容易读懂。
3.4 调整透明度与图层面板顺序
混合模式设好之后,效果可能偏暗。原因很简单,两个渐变图层叠加后,如果两个变量都是中等值,乘法结果会明显偏暗。
我的处理办法:把上层图层(冷色层)的整体透明度调到70%~85%区间。在“图层渲染”区域同样可以找到“透明度”滑块,这属于全局透明度,会同时作用于颜色和图例,直观有效。具体数值根据底图的明暗来微调,如果叠加后颜色太闷,就往高透明度方向调(即让上层更透明,露出更多底层)。
顺序上,冷色层放上面、暖色层放下面比较稳妥。两者谁上谁下在几何上是重叠的,但因为混合模式是非交换的,上层颜色的透明度设置会产生不同结果。我的经验是暖色层做“基底”,因为人的视觉对暖色更敏感,冷色上层轻微半透明再叠加,更容易形成“冷色在表面、暖色从底下透出来”的立体层次感。
3.5 检查四象限,微调分类阈值
图层叠加后,先不要急着导图。打开图层面板,右键暖色层,在“符号化”里临时把分类数改成2段试试,你会发现图面变成清晰的四色:低A低B、低A高B、高A低B、高A高B。再把分类数改成3段,图面变成9色。这就是你最终要面对的信息粒度。
如果发现某个象限(比如高A高B)明显没有几个区域,或者某个颜色占据了80%的图面,就要回去重新看数据。大概率有两个原因:一是两个变量高度正相关,高值区大量重叠,此时图面会以“两边都高”和“两边都低”为主;二是阈值切分方式不合适,比如用了等间隔法,偏态数据把大多数区域推到了低值区间。
调整阈值时,在符号化面板里修改“模式”和“类别”,QGIS会实时刷新地图画布。多次尝试后找到那个“四象限颜色数量相对均衡”的切法,通常就是成图效果最稳的状态。
4. 图例与配色方案打磨
4.1 为什么默认图例用不了
做完图层混合后,很多人第一反应是直接开“布局管理器”添加图例,结果发现图例里是两个图层各自的单变量渐变色带,完全不能表达网格矩阵的含义。这就必须手动画一个“二元图例”。
二元图例的常规形态是一个2×2或3×3的矩阵网格,横轴代表变量A从低到高,纵轴代表变量B从低到高,每个格子颜色对应地图里的混合结果。这个矩阵本质上就等价于“颜色查找表”,读者对照格子颜色,就能在地图上快速定位每个区域的组合类型。
QGIS默认的图例项不支持这种矩阵样式,所以绘制工作往往要放在“布局管理器”或外部绘图软件里完成。
4.2 手把手画一个矩阵图例
先说最简单的方式——直接在QGIS布局管理器里画。
- 打开“布局管理器”,新建一个布局,拖入地图后,再从左侧“添加图例”工具添加图例,后续把这个自动图例删掉只用来占位。
- 在布局里插入一个“矩形”或“多边形”元素,按照你的分类数复制若干份。比如3×3矩阵,就画9个小正方形,横排3个、竖排3个。
- 给每个矩形填充对应的颜色。填充色可以在右侧“项目”面板的“符号”里手动设置RGB值,然后逐一和地图主体配色的9个色值对齐。这个方法看起来笨拙,但胜在纯QGIS环境内完成,不依赖其他软件。
- 在每个矩形下方或左侧添加“标签”元素,写上“变量A低”“变量A高”“变量B低”“变量B高”,并用箭头或渐变示意方向。
如果你手头有Inkscape或者PPT,更省力的做法是在外部画好一个矩阵图例,导出成SVG或PNG,再拖进QGIS布局管理器里。这样排版自由度更高,字体也好控制。需要注意导出PNG的分辨率至少300dpi,否则打印出来会糊。
4.3 配色到底怎么选才不容易翻车
选色是整个流程里主观性最强、也最需要克制的一环。二元分区着色图的基础逻辑是暖色和冷色作为两个“坐标轴”,但具体用什么暖色、什么冷色,有讲究。
色盲友好是首要考虑。红绿组合看着很传统,但对红绿色盲读者基本无效。更稳妥的替代是“橙色vs蓝色”或“橙黄色vs蓝紫色”,这两种搭配在多种色觉异常情况下依然能区分。另一个被大量专业图表采用的方案是“酒红vs蓝灰”,优雅且对比度适中。
如果你用的是QGIS官方默认的“RdYlBu”(红-黄-蓝)作为暖色层、“BuGn”(蓝-绿)作为冷色层,叠加出的颜色容易显得脏。原因是黄色和绿色混合后会产生很难看的黄绿色,干扰信息表达。我更推荐用“OrRd”(橙-红)或“YlOrBr”(黄-橙-棕)这种高饱和度暖色,配“GnBu”(绿-蓝)或“PuBu”(紫-蓝)作为冷色,叠加后的中间色更干净。
具体在QGIS里操作:符号化 → 渐变 → 点“颜色渐变”下拉框 → “新颜色渐变”,可以选择颜色范围和对应的色带方案。
5. 视觉陷阱与更进一步的延展
5.1 最常见的三种“误读陷阱”
成图出来之后,不等于大功告成。我在实际项目里被别人问过很多次,发现读者在解读二元分区图时经常掉进三个坑:
第一个坑是“把归一化后的高低当成绝对数值的高低”。如果你的变量是经过分位数归一化的,那“高”只代表“在样本里排名靠前”,并不意味着绝对值大。写报告时必须把图例和文字说明放在一起,最好注明“颜色深浅基于分位数排名”。
第二个坑是“把高A高B当成正相关证据”。二元图只展示两个变量的组合分布,并不直接提示相关性大小。哪怕两个变量完全独立,也会有四象限颜色同时出现的局面。想严谨地谈相关性,得配合散点图和相关系数,地图本身说明不了因果或相关。
第三个坑是“色彩感知强度差异”。人眼对不同色相的敏感度不一致,暖色调往往比冷色调显眼,同样的饱和度下,红色比蓝色更容易抓住视线。如果两个变量重要程度相当,选色时要故意压低暖色的饱和度、稍微调高冷色的对比,才能在图面上达成“视觉平衡”。这个细节是我在反复调整中摸索出来的,市面教程很少提到。
5.2 验证你的图:和散点图互相印证
很多时候颜色配得眼花缭乱,自己也拿不准到底反映得准不准。我的习惯是:在QGIS里同步打开两幅面板,左边是地图,右边是这两个变量的散点图。
把散点图的横轴设成变量A,纵轴设成变量B,每个点对应地图里的一个面要素。然后回到地图上,目测高A高B区域对应散点图右上象限的点,高A低B区域对应右下象限。两边高度一致,说明颜色切分和阈值设置成功;如果散点图右上象限的点在地图上呈现得很少,反而中间色调区域很多,那就说明色带起点太高或阈值选择不当,需要回炉。
5.3 如果你还想更进一步
二元分区着色图的可扩展空间其实很大。最常见的方向是把时间维度加进去:比如同一指标在不同年度的二元关系,可以用分面地图按年份排列,形成一个小型时序系列。另一种做法是做“差异对比”,把时间1的数值减去时间2的数值作为两个变量,正负方向分开建模,就能用二元色展示“谁升了、谁降了、谁一升一降”的复杂格局。
插件方面,QGIS官方的插件仓库里有个叫Bivariate Renderer的插件,可以简化部分流程,不过它本质也是帮你快速配置双色渐变图层,熟练之后手搓反而更可控。建议先把手动流程跑顺,再考虑插件提速。
6. 常见问题与排查技巧实录
6.1 高频问题速查表
| 现象 | 可能原因 | 快速处理 |
|---|---|---|
| 叠加后图面大面积发黑 | 混合模式为“乘法”且两个变量高值区大量重叠 | 降低上层图层透明度,或把分类阈值调低 |
| 颜色灰蒙蒙、对比度低 | 色带浅色起点太高,或数据归一化后分布集中 | 换用对比度更强的色带,检查直方图 |
| 图层一关掉另一个,颜色就变 | 图层混合依赖两个图层同时开启 | 导出图片前务必确认两个图层都处于可见状态 |
| 添加图例后自动出现两份单变量图例 | 未手动创建矩阵图例 | 按第4.2节手工制作矩阵图例 |
| 字段计算时提示表达式错误 | 字段名带空格或中文导致语法问题 | 用双引号包裹字段名,表达式写"my field" |
| 图上位置偏移,两个图层对不上 | 复制的图层坐标系不同,或开启了几何纠正 | 确认两个图层都使用同一CRS,检查“图层属性→信息” |
| 找不到“混合模式”选项 | QGIS版本差异导致菜单位置不同 | 在图层渲染/透明度菜单下找,新版本在“符号化”选项卡底部 |
6.2 QGIS版本差异带来的坑
QGIS从2.x升级到3.x之后,很多菜单位置变了。老教程里常写的“图层属性 → 样式 → 图层混合模式”,在3.28 LTR版本里对应的路径是“图层属性 → 符号化 → 图层渲染”。如果你打开属性框发现找不到“混合模式”,八成是版本界面调整了,到右侧滚动条下面的“图层渲染”区域找,那个位置有“图层混合模式”下拉菜单和“不透明度”滑块。
另外,新版本的符号化对话框默认预览速度更快,但大量要素叠加实时刷新会卡顿。我在做全市几千个街道级别的二元图时,开着两个图层反复拖动阈值,画布经常掉帧。解决办法是在“视图”菜单里关闭“实时地图更新”,或者在“项目 → 属性 → 渲染”里开启“仅在地图交互时渲染”模式,调整完阈值再一次性刷新。
6.3 输出与导出环节的几点经验
成图之后要导出,一般有两种方式。一种是直接用“布局管理器”里的“导出为图片”,适合插到PPT和报告里;另一种是从菜单栏“项目 → 导入/导出 → 导出地图为图片”,可以在不进入布局的情况下快速输出当前画布。
导出时分辨率务必手动设置,别用默认的96dpi。我做A4幅面报告时,一般设300dpi,导出的PNG清晰度足够出版印刷。如果只要屏幕展示,150dpi就够了,文件体积也小很多。
还有个小细节:导出前最好把两个数据图层以外的辅助要素(比如标注、装饰层)单独归到一个组里,后续改动方便,也不容易误删。
最后分享一点个人经验
我做多变量可视化已经有几年时间,踩过不少坑之后,现在养成的习惯是:动手做二元分区着色图之前,先花两分钟拉一张两个变量的散点图,看看相关方向和数据分布。这步几乎不花时间,但能提前预判成图后颜色分布是否均匀、四象限是否会出现大面积空白。如果两个变量高度相关,我会考虑换变量,或者干脆回到两幅单变量图,毕竟可视化是为了帮助理解数据,不是为了炫技。
另外,再分享一个小技巧:如果你经常要在不同项目里复用同一套配色和分类方案,可以在图层符号化设置里把配色方案保存为快捷键方案,或者把调好的图例做成布局模板。这样下次拿到新数据,只需要替换数据源、刷新字段,几分钟就能产出一张风格统一的图。真正熟练之后,你会觉得二元分区着色图并不神秘,它只是帮你把两个维度整整齐齐地摆在了一张画布上。