做遥感这两年,但凡用Google Earth Engine(GEE)做过矢量数据处理的,应该都绕不开FeatureCollection这个类型。我第一次被它折磨是在批量统计行政区的NDVI均值,写了几行代码跑不通,最后发现是FeatureCollection和Feature没分清楚,属性字段的访问方式完全不一样。后来在实战里一点点试错、翻文档、看别人代码,才算把这个数据类型吃透。今天借这个机会,把这部分内容系统整理一下,给刚入门GEE的朋友做个参考,也给自己做个沉淀。
这个系列我打算分几篇来讲,第一篇先把FeatureCollection最核心的概念、构建方法、常用操作和常见坑讲清楚。适合刚接触GEE、对矢量数据操作还不熟的人,也适合已经写了一些代码但在数据类型上经常报错的人。内容偏实操,我会把我在项目里真正用过的代码、踩过的坑、查过的官方文档都揉进来,尽量做到拿到就能用。
1. 整体设计与思路拆解:FeatureCollection是什么,为什么非要搞懂它
1.1 数据类型的层级关系:从Geometry到Feature再到FeatureCollection
要理解FeatureCollection,首先要搞清楚GEE里矢量数据的三个层级关系。最底层的是Geometry,就是点、线、面这些几何对象本身,比如ee.Geometry.Point([116.39, 39.9])只是一个坐标点,它不带任何语义信息,不知道这是什么地方、有什么属性。在Geometry之上是Feature,它等于Geometry加上一组属性,比如一个点加上“城市名:北京”“人口:2000万”,这才构成一个有意义的空间要素。最外层是FeatureCollection,它是一组Feature的集合,相当于一个矢量图层的抽象。
你可以拿Excel表格来类比。Geometry是表格里某个单元格的坐标(或者叫位置信息),Feature是表格里的一整行,包含唯一标识符和若干字段,FeatureCollection就是整个表格加上每一行对应的空间位置。平时我们在ArcGIS或QGIS里打开的shp文件,加载到GEE里返回的就是FeatureCollection。很多新手上来就想直接操作FeatureCollection,结果发现它不是一个简单对象,里面包含了很多Feature,而每个Feature又包含Geometry和properties两部分,操作方式完全不一样。
1.2 为什么GEE选择用FeatureCollection作为矢量的核心容器
GEE是一个云端计算平台,最大的特点是分布式计算。它的数据不是存在你的本地硬盘上,而是分布在全球的数据中心。这就要求所有的数据类型必须是服务端对象,可以被序列化、分发到不同的计算节点上去并行处理。FeatureCollection正是为这种场景设计的,它本质上是一种非物化的集合,定义的是“如何获取数据”的逻辑描述,而不是把所有数据一次性拉到本地。
这意味着一个很重要的事情:在GEE里,FeatureCollection的操作绝大多数是惰性执行的,你调用filter、map、reduce的时候,数据并没有真正被处理,而是构建了一个计算图,直到你调用getInfo()、evaluate()或者通过Export导出时才会真正执行。这也是新手最容易困惑的地方,明明写了筛选条件,打印出来的集合大小却没变,因为服务端的数据还没跑过来。
第二个原因是FeatureCollection天然支持空间索引和分布式的并行计算。GEE内部对FeatureCollection做了分片存储,一个上百万要素的集合被切成了很多块,分散在集群的不同节点上。当你要做空间连接、缓冲区叠加、属性统计时,框架会自动把这些任务并行化,大幅提升计算效率。要是把数据全拉到本地再用GeoPandas处理,那根本不是一个量级。
1.3 使用场景:什么时候你离不开FeatureCollection
FeatureCollection在GEE里的使用频率非常高,我列几个最典型的场景。第一类是行政区统计,比如你有一份全国省级行政区划的FeatureCollection,想统计每个省过去十年平均降水量,你会用reduceRegions把栅格数据按矢量边界分区统计,输出结果还是一个FeatureCollection。第二类是站点数据的空间化,比如一批气象站点的坐标和观测值,转成FeatureCollection后可以插值、可以按缓冲区提取栅格值。第三类是空间查询和几何运算,比如两条道路线的相交分析、点要素落在哪个面要素里的判断,这些底层都要操作FeatureCollection。
还有一类容易被忽略的场景是数据清洗与合并。比如你从不同数据源拿到的表格,需要统一字段名、统一坐标系,甚至要做属性表的纵向拼接和横向连接,这些操作GEE都提供了对应的API,底层操作对象就是FeatureCollection。可以这么说,凡是涉及到“多个带属性的空间对象”的数据处理,基本都绕不开FeatureCollection。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节解析与实操要点:Feature和FeatureCollection的构建方法
2.1 Feature的构成:Geometry与properties,以及两者的关系
构建FeatureCollection之前,必须先掌握Feature本身。一个Feature由两部分组成:geometry和properties。geometry是一个Geometry对象,可以是Point、LineString、Polygon或者Multi系列,甚至可以是空几何(ee.Geometry())。properties是一个字典对象(Dictionary),存储的是属性字段和对应的值,键必须是字符串,值可以是数字、字符串、数组等基础类型,也可以是嵌套对象。
这里有一个关键点需要注意:GEE对Feature的property有严格的命名限制。属性名不能以数字或下划线开头,也不能包含空格和特殊字符,比如1st_band、_id这种都是不合法的,官方文档明确写了属性名必须匹配[a-zA-Z][a-zA-Z_0-9]*这个正则。我刚开始写代码的时候,从CSV导进来的字段名是“2019_population”,直接拿来构建FeatureCollection就报错了,后来改成pop_2019才通过。还有一点,属性值不能是复杂对象比如ee.Feature本身,但是可以存放ee.Number、ee.String、ee.List、ee.Dictionary这些对象。
创建单个Feature的代码很简单,下面是我在项目里最常用的几种写法,注释里写了适用场景:
javascript复制// 写法一:直接指定几何和属性,适用于临时构建点数据
var point = ee.Feature(
ee.Geometry.Point([116.39, 39.9]),
{name: '北京', population: 21540000}
);
// 写法二:只用几何,属性留空,适用于只做空间分析、不需要属性表的场景
var polygon = ee.Feature(ee.Geometry.Polygon([[
[116.3, 39.8], [116.6, 39.8], [116.6, 40.1], [116.3, 40.1]
]]));
// 写法三:从GeoJSON构建,适用于在外部GIS软件里准备好数据再引入
var geojson = {
type: 'Feature',
geometry: {type: 'Point', coordinates: [116.39, 39.9]},
properties: {name: '北京', population: 21540000}
};
var featureFromJson = ee.Feature(geojson);
2.2 从零构建FeatureCollection:直接传入、fromGeometry、fromFeatures
构建FeatureCollection最常见的方式是传入一组Feature数组,GEE会把它封装成一个服务端集合。比如你的研究区有五个城市,要构建一个点要素集合,代码如下:
javascript复制var cities = ee.FeatureCollection([
ee.Feature(ee.Geometry.Point([116.39, 39.9]), {name: '北京'}),
ee.Feature(ee.Geometry.Point([121.47, 31.23]), {name: '上海'}),
ee.Feature(ee.Geometry.Point([113.26, 23.13]), {name: '广州'}),
ee.Feature(ee.Geometry.Point([104.06, 30.67]), {name: '成都'}),
ee
