1. 为什么说“分类字段选择”是QGIS里最容易被低估的一步
如果你刚接触QGIS,大概率第一次做符号化时就在图层面板里找到了“分类”标签页,然后在“列”下拉框里随便选了一个字段,点击“分类”,颜色出来了,看着还像那么回事。但真正用过一段时间后你会发现,同样是点一次“分类”,字段选成文本还是数字,结果可能截然不同:文本字段分类出来的图例顺序是按拼音首字母排的,数字字段是按数值大小排的;文本字段能用“唯一值”渲染几万个类,数字字段这样干会直接把图层卡死;就连标签里想显示一个简短的地名,字段类型选错了,表达式怎么改都报错。
所以这篇文章要聊的是“分类字段选择”背后的逻辑:QGIS里文本字段和数字字段到底有什么区别,选错会带来什么结果,以及在实际项目中怎么判断、怎么操作、怎么避坑。这里说的“分类字段”,不只是符号化里面那个下拉框,它同样影响标签、图例、表达式计算、栅格重分类,甚至从PostGIS或者Oracle里读进来之后的行为方式。适合刚入门想要搞清楚QGIS图层属性的人,也适合已经做了几个项目但总被图例顺序、字段类型搞蒙的从业者。
先说一个基本定论:QGIS不是把字段类型当摆设的。它严格按照字段的存储类型来决定排序、匹配、渲染和表达式运算的方式。数字字段就是数字,能做算术、能参与重分类、能按数值区间自动分级;文本字段就是字符串,能做的就是匹配、拼接、转码。理论上把全部字段都存成文本也能出图,但这样做是给自己长期用埋雷,我实测无数次,只要涉及图例排序和属性筛选,文本类型会把很多本来几秒钟就能做完的操作拖成几十分钟的返工。
下面我会从QGIS的实际界面出发,把分类字段选择的完整逻辑拆开讲。从字段类型的基础判断,到符号化里的具体操作,再到标签和栅格重分类里的应用,最后把高频问题整理成一份避坑速查。所有操作都以QGIS 3.x系列为准,版本差异我会在关键节点标注一下。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手选字段前,先看懂QGIS里的字段类型体系
2.1 打开属性表,一眼判断字段是不是数字
做分类之前,第一件事不是看图,而是打开图层的属性表。在图层上右键,选择“打开属性表”,面板顶部就是这一层的字段列表。QGIS 3.x版本里,字段名称下面会带一个类型标识:
- 字符串:字段名旁边会显示一个字母“abc”或者“String”字样
- 整数:显示“整数”或“int”类型标记
- 浮点数:显示“双精度”或“浮点”标记,通常是“real”“double”或者带小数的数字
- 日期:显示“日期”标记,QGIS里区分日期型和字符串日期
比较早期的QGIS版本里面,直接在属性表列标题上看到字段类型,鼠标悬停在字段名上会弹出类型提示。3.10以后的版本在图层属性的“字段”选项卡里更直观,左侧是字段列表,右侧可以直接看到类型和长度。
实际操作里判断类型最靠谱的两个入口:
- 图层属性 → 字段选项卡:这里能看到每个字段的“类型”列,比如“字符串(80)”“整数(32位)”“双精度(64位)”等
- 字段计算器:打开后双击任意字段名,看表达式对话框里该字段是否被归入“字段和值”类别,并且字段类型不同,可用的函数是动态变化的
一个实用小技巧:如果你看到的类型是“整数(32位)”或者“双精度”(64位),那它就是妥妥的数字字段,可以直接用于分类、排序和算术运算。如果是“字符串(80)”,哪怕它里面存的是一堆“001”“002”这样的编号,系统也只会把它当文本处理,按字母顺序排序时会出现“1、10、100、2、20”这种怪异顺序。
2.2 文本字段和数字字段在处理逻辑上的本质差异
很多新手会把“看着像数字”和“真的是数字”混为一谈。QGIS底层用的是SQLite、PostGIS、Oracle这类数据库引擎来管理属性数据,字段类型直接决定了数据帧里的存储方式和比较规则。
数字字段使用的是数值型数据结构,它在内存中占用固定长度,比较时直接按数值大小进行,所以分类渲染、图例排序、区间统计都能使用数值逻辑。比如你用“唯一值”分类一个整数型字段,QGIS会把值从小到大排列;你用“分级”做5级配色,它能把数值范围自动切割成5段,分段方式可以选等间距、分位数、自然断点(Jenks)等。
文本字段则完全不同。它在比较时使用的是字符集字典序,也就是按下层数据库的collation规则排序。对中文来说,底层排序规则常见的有三种情况:按拼音排、按Unicode码点排、按字节流排。这也是为什么文本字段分出来的图例顺序经常“看着没规律”。更麻烦的是,文本字段不能直接参与算术运算和数值区间判断,表达式里写 "area_m2" > 100 这样的条件,一旦字段是字符串,结果就是直接报错或者返回NULL,因为数据库没法拿字符串和一个数字比大小。
举一个我调过的真实案例。有个项目里,从Excel导入的行政区面积字段被QGIS自动识别成了字符串,因为原始表格里某些单元格带有空格或者千分位逗号,比如“1,234.50”这种格式。符号化时大家都以为面积是数字,用自然断点分类,结果QGIS按照字符串规则把所有值拆成了几百个唯一类,图例爆炸,地图上每个多边形一个颜色,根本没法看。这就是字段类型没有确认好就匆匆分类的典型后果。
2.3 外部数据导入时的类型陷阱:CSV、Excel、Oracle、PostGIS
QGIS最常见的字段类型问题,不是在桌面端手工建的图层,而是从外部数据导入时发生的。
CSV文件是重灾区。QGIS读取CSV时会自动推断每列的类型,它判断的规则是“从前8行扫描,如果该列所有非空值都能被识别为数字,就按数字读取;否则按字符串读取。”如果你的CSV里前面几行面积列都是正常的数字,但中间某一行成了“1,234.5”或“—”,QGIS会整体判定为字符串。等你做符号化时才发现面积字段是字符串,这时候再去属性表里修改字段类型已经晚了,因为原数据已经带着文本进入图层,最佳做法是在数据源管理器里调整“解析为数字”的选项,或者先把字段在Excel里清洗干净再导入。
Excel文件(xlsx)相比之下好一些,因为Excel本身有单元格格式的概念,QGIS读取时会参考单元格样式。但前提是这个文件在保存时没有把长数字变成科学计数法,也没有把代码列设置成“文本”格式。我带过一个学生做的三调符号化项目,他搞到的Excel里所有的指标代码列都被Excel自动加了绿色三角标记,导入QGIS后全部变成文本,代码“0101”被读成了字符串而非整数,导致后续用代码字段做唯一值分类时,图例顺序完全乱套。
Oracle和PostGIS数据库里的表相对规范,因为数据库层面的字段类型是明确声明的,VARCHAR2、NUMBER、INTEGER、CHAR这些都有严格语义。需要小心的反而是连接时使用了不正确的驱动或者自定义视图,比如Oracle中有的字段虽然存的是数字,但在SQL视图里把TO_CHAR写成了SELECT的一部分,字段就变成了文本类型。热词里提到的“Oracle 字段以逗号隔开”是一种特殊的数据存储方式,后面我在讲代码值转文本的时候会单独说明。
所以我的习惯是:任何外部数据进入QGIS后,做任何分析前,强制打开属性表,把每一个准备参与分类、标签、统计或重分类的字段的类型全部过一遍。花两分钟确认,比后面花两小时排查一次分类异常要划算得多。
3. 分类字段选择的完整实操流程
3.1 从图层属性到“分类”页面的操作路径
第一步,打开图层面板,右键需要处理的图层,选择“属性”,在弹出的对话框里切到“符号化”选项卡。符号化是QGIS里控制图层显示方式的核心入口,里面默认是“单一符号”,把它切换为“分类”。
切换成“分类”之后,界面会出现几个关键控件:
- 列:也就是分类字段选择器,点后面的下拉箭头可以选择图层中的任意字段
- 色带/颜色渐变:控制分类结果的颜色过渡
- 符号:设置图例符号的样式,比如点、线、面的大小和填充
- “分类”按钮:一旦字段选好,点击它就会执行分类,在下方列表生成各个类别的图例项
这里有一个QGIS用户很常用的扩展操作:点击列下拉框旁边那个“表达式”按钮(通常是一个带fx的图标),可以直接写表达式来生成一个动态字段,不需要在数据表里新建字段。比如想按面积大小分成若干档,可以写 CASE WHEN "area" < 1000 THEN '小' WHEN "area" < 10000 THEN '中' ELSE '大' END 这样一段表达式,生成的分类结果就会显示“小”“中”“大”三个类别。
字段选择器一旦选中数字字段,下方会出现“精确数目”的选项,你可以手动输入分类数量;如果选中文本字段,“精确数目”选项就不生效,因为它按唯一值枚举,没法自动合并。这个区别是很多人容易忽略的:文本字段即使选了“精确数目=5”,QGIS也只会在图例列表里显示前5个唯一值,而不是自动分5组。
3.2 文本字段分类和数字字段分类的界面差异
在实操里面,文本字段和数字字段在分类界面里至少有四个明显的区别。我建议你打开QGIS,用同一个数据集分别试一次,感受比看文字描述直观得多。
第一,分类机制不同。 文本字段按唯一值枚举执行,有多少个不同值就生成多少个类。如果一个乡镇属性表里的“村名”字段有20个不同的值,分类后就是20个类,颜色由色带自动映射。数字字段除了唯一值,还额外支持区间自动分组。比如用“县级代码”这种只有几个值的整数做分类,QGIS也会默认做唯一值,但真正发挥数字优势的是面积类字段,配合“分级”样式能按值域切片。
第二,图例顺序逻辑不同。 文本字段分类后,图例列表默认按字母顺序(英文)或拼音顺序(中文,取决于区域与排序规则)排列,2位数数字会按字符顺序排列。数字字段分类后,图例按数值顺序排列,唯一值从大到小,分级后也是按数值区间从小到大的顺序呈现。
第三,符号级别和颜色映射的灵活性不同。 数字字段做分级后,可以随时右击图例列表,选择“反转图例顺序”,也可以手动调整每个区间的上下限。文本字段不行,它每个类就是一个固定的字符串值,你想合并“已入库”和“入库完成”为同一个分类,只能通过修改数据本身或者写分组表达式来实现。
第四,数据量耐受度不同。 如果你的数字字段有5000个不同的整数值,切到“唯一值”做分类,图层面板会卡一会儿,但通常还能撑住;如果是一个有5000个不同文本值的字段,同样操作可能会明显卡顿,因为字符串比较比数值比较更慢,而且在渲染时每个类别都要做一次字符匹配。
还有一条很实用:如果你需要按照“文本代码”做分类,但希望图例顺序按某个数字字段排序,正确做法是以数字字段为主分类字段,再通过图例标签格式化把代码转成对应文本。QGIS的“分类”列表里每一行都可以双击修改“标签”列,这个标签只影响显示,不影响实际分类逻辑,所以你可以用数字分类保证顺序,再用标签替换显示文本。这是QGIS里一个非常常用的伪“文本分类顺序修正”手段。
3.3 图例管理与分类结果微调
分类结果生成以后,图例项会出现在符号化页面下半部分的列表中。每个图例项包含三列:符号预览、值、标签。你需要知道几个高频操作:
- 双击“值”单元格可以修改该分类的匹配值;双击“标签”单元格可以修改图例中的显示文本,不影响匹配
- 选中多个图例项(按住Ctrl或者Shift),点击“合并选中的类别”,能把多个值合并成一个类别,比如把“空地”和“空置土地”合并为“未利用地”
- 点击“删除选中的类别”,可以移除不想要的类别,但要注意图形显示时未匹配到的值会用默认符号隐藏或显示
- 右键图例列表,可以调整符号样式、复制符号、批量上色
实际项目中,我最常用的一个微调是:在分类列表生成后,把数字字段的“值”列改成一个格式化字符串。比如用面积字段做分级,双击“值”列后把显示的值改成“0-100(含)”“100-300(含)”这样的区间描述,然后再把标签列也联动修改。这样导出的图例就非常接近规划图纸上常见的形式,而不是QGIS默认的“[0,100]”这样的数学区间写法。
如果分类出来的结果不是你要的效果,不要反复点“分类”按钮。正确做法是先改字段选择、调整表达式或数据,再重新分类。每次点“分类”都会清空手动修改过的标签、符号和合并设置,这个小坑让不少人在图例调整阶段白做了几分钟的重复劳动。
注意:QGIS 3.x中,“分类”按钮每次点击都会将图例列表重置为基于新字段/新表达式的全量结果。如果只是想看不同色带效果,改完色带后不要重新点“分类”,直接在列表下方滚动查看即可。
4. 进阶应用:从分类字段到标签、表达式和栅格重分类
4.1 字段类型在标签表达式里的判断规则
分类字段选择不只是符号化的“列”下拉框那么简单,它直接决定了标签表达式能不能正确计算。打开图层属性 → “标签”选项卡,单值标签模式下有一个表达式编辑区域,这个区域就是标签文本的来源。
和符号化一样,标签里引用字段时,QGIS也严格区分类型。比如 concat("省份", "面积") 这种写法,如果“面积”是数字字段,concat函数会先将数字转成字符串再拼接,结果能正常显示;但如果反过来,你想在标签里显示“该区域面积为XXX平方米”,写 '该区域面积为' || "面积" || '平方米',数字字段也会被自动转换成字符串拼接。关键不是“字符串能不能拼数字这样写”,而是如果你对数字字段做了 "面积" + 1 这样的算术运算,它的结果是数值;对文本字段做 "面积" + 1,表达式会直接报错,因为字符串加整数在SQL表达式引擎里是不允许的。
实际项目里最常见的标签问题是:面积字段在数据表里是字符串,标签里写 round("面积", 1) 想保留一位小数,结果运行时报错,或者结果为空。原因就是round函数要求参数是数值型,字符串进去直接被判定为不可用。
因此我建议养成一个好习惯:在给图层做任何标签之前,先确认所有参与标签的字段类型。如果发现某个数字字段被存成了文本,不要急着在表达式里用to_real函数强行转换(那是临时方案,每次都写很麻烦),直接用属性表里的“字段计算器”创建一个新的数字字段,或者用图层属性 → 字段选项卡里的“编辑字段”功能把类型改成数字。
4.2 代码值转文本:ID字段如何显示成对应名称
热词里有一条非常醒目的需求:“把id转成对应的文本”。这在QGIS里至少有两种常用实现方式,我分别说一下适用场景。
方式一:用字段计算器 + CASE WHEN 表达式。 如果代码和文本的映射关系是固定的、数量不多(比如状态码只有几个),直接在表达式里写:
sql复制CASE
WHEN "status_code" = 1 THEN '待审核'
WHEN "status_code" = 2 THEN '已审核'
WHEN "status_code" = 3 THEN '已驳回'
ELSE '未知'
END
把这段表达式输入到字段计算器的“输出字段名”里,创建一个新的文本字段,然后标签或者分类都引用这个新字段。优点是结果作为一个真实字段存储在属性表里,后续任何操作都可以用;缺点是映射关系一旦变化,你就要重新计算一次字段。
方式二:连接(Join)一张代码对照表。 如果你手里有一张Excel或CSV,里面是ID和名称的对应关系,最正规的做法是使用图层面板“连接”功能。具体操作是:图层属性 → “连接”选项卡 → 添加连接 → 选择代码对照表,指定“连接字段”和“目标字段”,然后图层就会额外获得一个名称字段。连接成功后,标签和分类里都可以直接用这个名称字段,不需要合并进原数据。
关于“Oracle 字段以逗号隔开”的说明: 有些数据库表为了节省空间,会把一个字段存成逗号分隔的多个ID,比如“1,3,7”表示多个状态。这种设计在空间分析里非常讨厌。如果需要把ID序列转成文本名称序列,一般有两种思路:一种是在数据库里用正则拆分成多行,再与代码表关联;另一种是在QGIS里先转成数值列表,再通过数组函数做映射。前者推荐在Oracle或PostGIS里完成,后者在QGIS表达式里也能实现:
sql复制array_to_string(
array_foreach(
string_to_array("ids", ','),
CASE WHEN @element = '1' THEN '甲'
WHEN @element = '2' THEN '乙'
ELSE '未知'
END
),
','
)
这段表达式的逻辑是:先把逗号分隔的字符串切成数组,然后对每个元素作映射,最后再用逗号拼回去。用这种方式,即使字段是以逗号隔开的ID也能在分类和标签里看到对应的文本名称,不需要在数据库里写复杂SQL。
4.3 栅格重分类场景中的字段要求
热词里有“qgis 栅格重分类”和“qgis三调符号库”,这两个场景其实都和字段选择有关联。
栅格重分类(Raster Reclassify)在QGIS里通常借助“SAGA”或“GDAL”工具,输入是栅格值的分段规则。这个过程中虽然不直接操作属性表的文本或数字字段,但你在写“重分类表”时,上下限字段会被当作数字处理,如果你从Excel复制了一套带文本格式的分段规则进来,工具很容易报错。所以栅格重分类前,同样要检查重分类表里的上下限字段是不是纯数字。
三调符号库则是一个典型的分类字段场景。三调数据里每个地类图斑都有一个地类编码,通常是三位或四位数字,比如“0101”“0102”这种。做三调符号化时,正确姿势是用编码字段(数字或文本均可)做唯一值分类,再通过三调符号库的符号样式匹配编码,图例显示的是编码,标签则可以使用连接表或表达式将编码转换成地类名称文本。如果你直接把地类名称字段做分类字段,会遇到两个问题:一是名称字段可能含有空格、错别字、前后不一致,导致图例爆炸;二是名称的排序没有固定规则,图例顺序很难按国标顺序排列。所以三调项目的经验是:分类字段用编码,显示字段用名称,对不上的时候优先检查数据字典。
还有一个点,如果你在“qgis 导出 shp 文件”时发现导出的属性表里数字字段变成了文本字段,这多半是字段计算器在创建字段时输出类型设置成了字符串。QGIS导出SHP时,会自动把虚拟字段和部分表达式字段按字符串处理,所以如果你用虚拟字段做分类,导出SHP后很可能出现类型丢失的问题。要避免的话,记得在字段计算器里勾选“创建新字段”,并显式指定输出字段类型为数字。
5. 高频问题与排查技巧实录
5.1 为什么选对了字段,分类出来的颜色仍然不对
这个问题我在技术群里被问过很多次。选中的字段明明是数字字段,分类也生成了,但地图上有些多边形显示成了默认的灰白色,或者颜色区域和分类值对不上。排查思路通常是:
- 首先看属性表,检查那些“显示不出来”的空间要素是否真的存在,有些要素是数据表里没有任何值(NULL),分类的时候NULL不会被归入任何类别,需要使用“符号化 → 分类 → 勾选‘包括空值’”或者手动把NULL值单独设置成一个类别
- 其次看是否使用了“表示不匹配的值”的选项,QGIS里有一个复选框,勾选后未匹配的要素可以用单独的符号显示,否则会被隐藏
- 再检查坐标几何本身有没有问题,比如某些多边形是无效几何,渲染时被跳过,但这和分类字段其实没关系,需要用“修复几何”工具处理
我的习惯是:分类做完后,第一步不是看配色好不好看,而是先检查图例列表的“值”列里有没有明显缺失该有的值。如果值列完整,但地图上显示不对,再进入属性表做表连接检查。
5.2 图例顺序乱成一片,怎么快速恢复
图例排序问题是分类字段选择最常见的“灾后现场”。文本字段按字符排序,数字字段若被识别成文本,就会出现“1、10、100、11、2、20”这种经典乱序。
解决方法有两个层次。低层方案:把字段纠正成数字类型。在属性表里用字段计算器直接创建一个新字段,表达式写 to_int("原始字段"),输出类型设为“整数”,再用新字段做分类。这是治本的方案。高层方案:如果字段本身确实是文本(比如行政区代码),但你又想按自定义顺序排列,那就需要创建一个“排序字段”作为辅助,然后在分类表达式里同时引用排序字段和显示字段。也可以用我之前提到的“数字分类+标签替换”技巧,本质上都是借道数字字段的排序规则来得到有序图例。
还有一个容易踩的坑:即使字段是数字,QGIS对部分大整数(超过32位范围)也会产生精度问题。如果你有一个18位的统一社会信用代码、身份证号或者某类长ID,它即使存成数字字段,显示时也可能出现精度丢失变成“01000000000123456”。遇到这种字段,处理方式很简单:在数据库或Excel里就把它存成文本字段。ID类的长数字,从源头就应该用文本类型来存,而不是等进了QGIS再纠正。
5.3 从数据库导入的属性,字段类型和源库不一致怎么办
从PostGIS或Oracle导入图层时,偶尔会发生字段类型和数据库声明不一致的情况。比如Oracle里明明是一个NUMBER(10,2)字段,QGIS读出来却是“字符串”。这通常是因为连接时驱动把小数位格式化了,或者你用的是只读视图。
排查路径一般是:在QGIS浏览器里查看该图层的“属性”页面,确认字段类型;再检查数据库连接是否用了正确的SQL方言,比如在PostGIS里使用了::text转换,或者在Oracle里使用了TO_CHAR格式化。如果你用的是QGIS自带的“数据库管理器”连接Oracle,建议在SQL查询里显式使用CAST或TO_NUMBER函数,把关键字段明确转换为数字类型后再加载。
5.4 标签表达式报错:字段类型不匹配的排查口诀
写表达式报错是家常便饭。我能给的最实在的一条经验是:报错后先看错误提示框里被标红的函数名或字段名,然后去属性表确认该字段的类型。常用调试口诀如下:
round、ceil、floor、sum、avg这类函数报错,99%是字段不是数字类型concat、||、replace、substr这类字符串函数,对数字字段也能用,但如果你在拼接中混入中文引号或漏了引号,也会报错regexp_match报错时,优先确认正则字符串有没有用双引号,QGIS里字符串字面量必须用单引号,字段名用双引号,很多新手写反了- 表达式字符串中如果使用了“逗号隔开的多个值”作为条件,比如
IN ('A','B','C'),要确保这些值都是字符串或都是数字,不要混着写
另外一个我自己用过很多次的技巧:在表达式对话框里,双击字段列表中的字段名,QGIS会自动插入带引号的字段引用,比如 "面积"。然后鼠标悬停在字段名上,会显示出字段类型。如果你看到类型是“字符串”,但里面存的是数字,那就先做一个转换再参与计算。
5.5 导出后的SHP文件字段类型变化问题
用“另存为”功能导出SHP时,字段命名会被限制在10个字符以内,字段类型也可能发生细微变化。实测中,QGIS把虚拟字段、表达式字段导出为SHP时,会将其处理成字符串或双精度,具体取决于表达式输出类型。如果导出后其他软件(比如ArcGIS)里发现面积字段变成了文本,多数原因是你在QGIS里用了虚拟字段做面积计算,而不是在属性表里创建了真实数字字段。
解决办法是在导出前用字段计算器勾选“创建新字段”并指定输出类型为“浮点/双精度”,然后把原来的虚拟字段删掉。SHP这个老格式本身不支持所有类型,所以能用GeoPackage存数据的场景,我一般建议优先使用GeoPackage,它对字段类型的保留比SHP友好得多。
6. 一些长期经验总结
做QGIS项目这几年,我在分类字段选择这个细节上踩过的坑比在配图样式上多得多。归根结底,所有问题几乎都源于一个习惯:拿到数据后没有查看字段类型,就急于做符号化和出图。QGIS的字段类型体系其实非常严格,它不会帮你变通,只会按照你给定的字段类型去执行渲染和分析逻辑,所以源头确认远比事后补救重要。
选分类字段时的三句话我建议你贴在显示器旁边:一,凡是参与计算和分析的字段,必须是数字类型;二,凡是表示代码和ID的字段,即使内容是数字,也建议用文本类型保存;三,分类字段和显示字段可以分开,数字字段负责排序和计算,文本字段负责语义和标签。
掌握了这个核心原则,再去处理QGIS里的符号化、标签、数据库导入和导出,都会顺畅很多。以上内容是基于我自己在实际项目里反复调试得出的经验,版本更新可能会有细微差异,但大的框架是不会变的。你可以照着上面的流程试一次分类字段选择,大概率就不会再被图例顺序和字段类型的问题绊住脚步了。
