连接​​ee.Join​​​用于根据 ​​ee.Filter​​​ 指定的条件组合来自不同集合(例如 ImageCollection 或 FeatureCollection)的元素。
过滤器由每个集合中相互关联的属性的参数构成。具体来说,leftField 指定主集合中与辅助集合中的 rightField 相关的属性。
过滤器的类型(例如,equals、greaterThanOrEquals、lessThan 等)表示字段之间的关系。

连接的类型表示集合中元素之间的一对多或一对一关系以及要保留多少匹配项。
连接的输出由 ​​​join.apply()​​ 生成,并且会根据连接的类型而有所不同。

具体方法有:

  1. 只保留左侧数据集
  • 筛选符合条件的
ee.Join.simple()
  • 反选符合条件的
ee.Join.inverted()
  1. 两侧数据集均保留(数据集合并)
ee.Join.inner()
  1. 对符合要求的数据集以属性形式添加左侧数据集内
  • 用于确定符合要求的右侧数据集,结果标记在左侧新增属性字段内
ee.Join.saveAll()
  • 确定最优数据集,返回在属性字段内,只保留最优图像
ee.Join.saveBest()
  • 只保留右侧第一个符合要求数据影像
ee.Join.saveFirst()
  1. 空间连接(空间筛选器)
  • 基于距离对数据集进行连接
ee.Filter.withinDistance()
  • 基于几何位置进行连接
ee.Filter.intersects()

1. 只保留左侧数据集

筛选符合条件的

ee.Join.simple()
  • 代码详解
'用于筛选数据集影像之间相差times以内的数据集'
var filter_1 = ee.Filter.maxDifference(
{
difference: times,
'通过系统时间联系数据集(system:time_start)'
leftField: 'system:time_start',//左字段的选择器,类型为time_start,即从起始计时,单位毫秒
rightField: 'system:time_start' //右字段的选择器'
//注意:左右字段(Field)与左右对象只能选其一,如果有左右对象则无选择器(字段的单位已经存在);有选择器时,不能有对象,对象目前为未知
});
//其中times单位为毫秒,例如1天为1*24*60*60*1000

'定义一个空的simpleJoin,后边应用筛选器时是选择符合条件的结果'
var simpleJoin = ee.Join.simple();
'定义一个空的invetJoin,后边应用筛选器时是选择不符合条件的结果'
var invetJoin = ee.Join.inverted();

'对simpleJoin应用筛选器'
var simpleJoined = simpleJoin.apply(数据集1, 数据集2, filter_1);
print(simpleJoined); //可以打印查看满足条件的数据集1影像名称
  • 案例
// 引入Landsat8和Sentinal数据,利用重庆市点进行地理筛选
var L8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(ee.Geometry.Point(106.3737, 29.9262));
var Sentinel = ee.ImageCollection("COPERNICUS/S2")
.filterBounds(ee.Geometry.Point(106.3737, 29.9262));
// 筛选出2018年的图像
var L8_2018= L8.filterDate('2018-01-01','2018-12-31')
var ST_2018= Sentinel.filterDate('2018-01-01','2018-12-31')
// 定义1天的变量
var One_Day_Millis = 1*24*60*60*1000
// 通过maxDifference定义Sentinel图像获取前后一天内的图像
// 单位为毫秒,1*24*60*60*1000就是一整天
var L8_Within_Sentinel = ee.Filter.maxDifference({
difference: One_Day_Millis,
leftField: 'system:time_start',
rightField: 'system:time_start'
})
// 定义一个simpleJoin
var simpleJoin = ee.Join.simple();
// 应用SimpleJoin.
var simpleJoined = simpleJoin.apply(L8_2018, ST_2018, L8_Within_Sentinel);
// 打印结果.
print('Simple join: ', simpleJoined);

【GEE笔记6】数据连接Join_遥感

反选符合条件的

ee.Join.inverted()
  • 代码详解
'用于筛选两影像某字段之间满足条件的数据集'
var filter_1 = ee.Filter.eq(
{
leftField: '字段1名称',
rightField: '字段2名称'
});

'定义一个空的innerJoin,应用筛选器时是选择符合条件的结果'
var innerJoin = ee.Join.inner('名称1', '名称2');
//定义生成结果的合成两产品的名称

'对innerJoin应用筛选器'
var toyJoin = innerJoin.apply(数据集1, 数据集2, filter_1);
print(toyJoin);
//可以打印查看满足条件的两个影像名称,分别对应前边的名称1与名称2
  • 案例
// 引入Landsat8和Sentinal数据,利用重庆市点进行地理筛选
var L8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(ee.Geometry.Point(106.3737, 29.9262));
var Sentinel = ee.ImageCollection("COPERNICUS/S2")
.filterBounds(ee.Geometry.Point(106.3737, 29.9262));
// 筛选出2018年的图像
var L8_2018 = L8.filterDate('2018-01-01','2018-12-31')
var ST_2018 = Sentinel.filterDate('2018-01-01','2018-12-31')
// 定义1天的变量
var One_Day_Millis = 1*24*60*60*1000
// 通过maxDifference定义Sentinel图像获取前后一天内的图像
var L8_Within_Sentinel = ee.Filter.maxDifference({
difference: One_Day_Millis,
leftField: 'system:time_start',
rightField: 'system:time_start'
})
// 定义一个invertJoin
var Invet_Join = ee.Join.inverted();
// 应用invertJoin
var Invet_Join_Results = Invet_Join.apply(L8_2018, ST_2018, L8_Within_Sentinel);
// 打印结果.
print('Invet_Join: ', Invet_Join_Results);

【GEE笔记6】数据连接Join_云计算_02

2. 两侧数据集均保留(数据集合并)

并且会增加字段,表示左侧第几个位置和右侧第几个位置的数据符合筛选条件

ee.Join.inner()
  • 代码详解
'用于筛选两影像某字段之间满足条件的数据集'
var filter_1 = ee.Filter.eq(
{
leftField: '字段1名称',
rightField: '字段2名称'
});

'定义一个空的innerJoin,应用筛选器时是选择符合条件的结果'
var innerJoin = ee.Join.inner('名称1', '名称2');
//定义生成结果的合成两产品的名称

'对innerJoin应用筛选器'
var toyJoin = innerJoin.apply(数据集1, 数据集2, filter_1);
print(toyJoin);
//可以打印查看满足条件的两个影像名称,分别对应前边的名称1与名称2
  • 案例1
// 创建FeatureCollection_1.
var primaryFeatures = ee.FeatureCollection([
ee.Feature(null, {foo: 0, label: 'a'}),
ee.Feature(null, {foo: 1, label: 'b'}),
ee.Feature(null, {foo: 1, label: 'c'}),
ee.Feature(null, {foo: 2, label: 'd'}), ]);
//创建FeatureCollection_2.
var secondaryFeatures = ee.FeatureCollection([
ee.Feature(null, {bar: 1, label: 'e'}),
ee.Feature(null, {bar: 1, label: 'f'}),
ee.Feature(null, {bar: 2, label: 'g'}),
ee.Feature(null, {bar: 3, label: 'h'}), ]);
// 定义一个ee.Filter.equals,要求foo=bar.
var toyFilter = ee.Filter.equals({
leftField: 'foo',
rightField: 'bar'
});
// 定义一个innerJoin.包括左侧数据集的名称primary和右侧数据集的名称secondary
var innerJoin = ee.Join.inner('primary', 'secondary');
// 运用innerJoin.
// 打印结果. var toyJoin = innerJoin.apply(primaryFeatures, secondaryFeatures, toyFilter);

print('Inner join toy example:', toyJoin);

【GEE笔记6】数据连接Join_javascript_03

图中,有​​5个Feature​​​满足要求,编号为​​01234​​(编号是从0开始的,0就是第1个,4就是第5个)。

在编号为0的元素(element)中,也就是​​Feature 1_0​​​ ,左侧​​primary​​​的数据为​​primaryFeatures​​​里面的第2个,编号为1,也就是​​Feature 1 ---> ee.Feature(null, {foo: 1, label: 'b'})​​​,因为条件是​​foo eq bar​​​, 所以满足这个条件的右侧数据是​​ee.Feature(null, {bar: 1, label: 'e'})​​​,也就是第1个,编号为0,所以是​​Feature 0​​。

因此,第一个满足要求的数据就是​​Feature 1_0​​(左边第2个=右边第1个)

  • 案例2
    将相同时间段内的2个数据集连接成一个数据集合
// 定义时间filter.
var dateFilter = ee.Filter.date('2014-01-01', '2014-02-01');
// 引入 MODIS 图像(EVI产品).
var mcd43a4 = ee.ImageCollection('MODIS/MCD43A4_006_EVI')
.filter(dateFilter);
// 引入 MODIS 图像(Quality产品).
var mcd43a2 = ee.ImageCollection('MODIS/006/MCD43A2')
.filter(dateFilter);
// 定义Inner Join.
var innerJoin = ee.Join.inner();
// 定义ee.Filter.equals,通过“系统时间”联系两种产品.
var filterTimeEq = ee.Filter.equals({
leftField: 'system:time_start',
rightField: 'system:time_start'
});
// 运用Inner Join.
var innerJoinedMODIS = innerJoin.apply(mcd43a4, mcd43a2, filterTimeEq);
// 显示结果,结果为FeatureCollection.
print('Inner join output:', innerJoinedMODIS);
// 利用map命令将两种产品整合.
var joinedMODIS = innerJoinedMODIS.map(function(feature) {
return ee.Image.cat(feature.get('primary'), feature.get('secondary'));
});
// 打印结果.
print('Inner join, merged bands:', joinedMODIS);

【GEE笔记6】数据连接Join_云计算_04


​primary​​​数据有​​1个band(element)​​​,​​secondary​​​数据有​​19个bands(elements)​​​(如上图所示)整合后的数据集有​​20个bands(elements)​​(如下图所示)

【GEE笔记6】数据连接Join_GEE_05

3. 对符合要求的数据集以属性形式添加左侧数据集内

用于确定符合要求的右侧数据集,结果标记在左侧新增属性字段内

ee.Join.saveAll()
  • 代码详解
var filter_1 = ee.Filter.maxDifference(
{
difference: times,
leftField: 'system:time_start',
rightField: 'system:time_start'
});

var saveAllJoin = ee.Join.saveAll(
{
matchesKey: 属性名称,
ordering: 'system:time_start' //排序字段
ascending:true //升序
});

'对saveAllJoin应用筛选器'
var saveAll_Join_Images = saveAllJoin.apply(数据集1, 数据集2, filter_1);
print(saveAll_Join_Images);
  • 案例
// 引入Landsat8和Sentinal数据,利用重庆市点进行地理筛选
var L8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(ee.Geometry.Point(106.3737, 29.9262));
var Sentinel = ee.ImageCollection("COPERNICUS/S2")
.filterBounds(ee.Geometry.Point(106.3737, 29.9262));
// 筛选出2018年的图像
var L8_2018= L8.filterDate('2018-01-01','2018-12-31')
var ST_2018= Sentinel.filterDate('2018-01-01','2018-12-31')
// 定义1天的变量
var One_Day_Millis = 1*24*60*60*1000
// 通过maxDifference定义Sentinel图像获取前后一天内的图像
var L8_Within_Sentinel = ee.Filter.maxDifference({
difference: One_Day_Millis,
leftField: 'system:time_start',
rightField: 'system:time_start'
})
// 定义一个simpleJoin
var SaveALL_Join = ee.Join.saveAll({
matchesKey: 'Sentinel_Match', // 符合要求的时候形成的数据集的名称
ordering: 'system:time_start',
ascending: true
});
// 应用SimpleJoin.
var SaveAll_Join_Images = SaveALL_Join.apply(L8_2018, ST_2018, L8_Within_Sentinel);
// 打印结果.
print('SaveALL_Join: ', SaveAll_Join_Images);

【GEE笔记6】数据连接Join_遥感_06


【GEE笔记6】数据连接Join_遥感_07


新增的​​Sentinel_Match​​,把右侧的数据(sentinel)添加到左侧数据(landsat)中去(如上图所示)

确定最优数据集,返回在属性字段内,只保留最优图像

筛选符合条件的所有数据,通过差值选择最优的数据

ee.Join.saveBest()
  • 代码详解
var filter_1 = ee.Filter.maxDifference(
{
difference: times,
leftField: 'system:time_start',
rightField: 'system:time_start'
});

var saveBestJoin = ee.Join.saveBest(
{
matchesKey: 属性名称,
measureKey: 测量字段 //返回测量结果,例如时间差距毫秒 timeDiff
});

'对saveBestJoin应用筛选器'
var saveBest_Join_Images = saveBestJoin.apply(数据集1, 数据集2, filter_1);
print(saveBest_Join_Images);
  • 案例
// 加载Landsat8图像
var primary = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2014-04-01', '2014-06-01')
.filterBounds(ee.Geometry.Point(-122.092, 37.42));
// 加载 GRIDMET 气象图像数据
var gridmet = ee.ImageCollection('IDAHO_EPSCOR/GRIDMET');
// 利用maxDifference定义两种产品的最大时间差为2天.
var maxDiffFilter = ee.Filter.maxDifference({
difference: 2 * 24 * 60 * 60 * 1000,
leftField: 'system:time_start',
rightField: 'system:time_start'
});
//定义SaveBest join.
var saveBestJoin = ee.Join.saveBest({
matchKey: 'bestImage',
measureKey: 'timeDiff'
});
// 应用SaveBest join.
var landsatMet = saveBestJoin.apply(primary, gridmet, maxDiffFilter);
// 打印结果.
print(landsatMet);

【GEE笔记6】数据连接Join_javascript_08


【GEE笔记6】数据连接Join_数据集_09

只保留右侧第一个符合要求数据影像

ee.Join.saveFirst()
  • 案例
// 加载Landsat8图像
var primary = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2014-04-01', '2014-06-01')
.filterBounds(ee.Geometry.Point(-122.092, 37.42));
// 加载 GRIDMET 气象图像数据
var gridmet = ee.ImageCollection('IDAHO_EPSCOR/GRIDMET');
// 利用maxDifference定义两种产品的最大时间差为2天.
var maxDiffFilter = ee.Filter.maxDifference({
difference: 2 * 24 * 60 * 60 * 1000,
leftField: 'system:time_start',
rightField: 'system:time_start'
});
//定义SaveFirst join.
var saveFirstJoin = ee.Join.saveFirst({
matchKey: 'First_Image',
});
// 应用SaveFirstjoin.
var landsatMet = saveFirstJoin.apply(primary, gridmet, maxDiffFilter);
// 打印结果.
print(landsatMet);

【GEE笔记6】数据连接Join_数据集_10

【GEE笔记6】数据连接Join_数据集_11

  1. 空间连接(空间筛选器)

基于距离对数据集进行连接

ee.Filter.withinDistance()
  • 代码详解
var filter_1 = ee.Filter.withinDistance({
distance: 距离,
leftField: '.geo', //.geo特指空间属性
rightField: '.geo',
maxError: 10 //运行电脑最大缩放误差
});
  • 案例
// 引入Landsat-8图像并进行时间和地点筛选.
var primary = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2014-04-01', '2014-06-01')
.filterBounds(ee.Geometry.Point(-122.09, 37.42));
// 引入FLUXNET 站点数据.
var fluxnet = ee.FeatureCollection('ft:1f85fvccyKSlaZJiAta8ojlXGhgf-LPPNmICG9kQ');
// 定义空间筛选:筛选100km以内数据.
var distFilter = ee.Filter.withinDistance({
distance: 100000,
leftField: '.geo', // .geo 特指空间属性
rightField: '.geo',
maxError: 10
});
// 定义SaveAll-Join.
var distSaveAll = ee.Join.saveAll({
matchesKey: 'points',
measureKey: 'distance'
});
// 应用SaveAll-Join.
var spatialJoined = distSaveAll.apply(primary, fluxnet, distFilter);
// 打印结果.
print(spatialJoined);

【GEE笔记6】数据连接Join_遥感_12


【GEE笔记6】数据连接Join_云计算_13

左侧数据集和右侧数据集都会被保存起来,左侧被保存为​​feature​​​,右侧被保存为​​geometry point​​。

基于几何位置进行连接

ee.Filter.intersects()
  • 代码详解
var filter_1 = ee.Filter.intersects({
leftField: '.geo', //.geo特指空间属性
rightField: '.geo',
maxError: 10 //运行电脑最大缩放误差
});
  • 案例
// 引入加州行政边界.
var cali = ee.FeatureCollection('ft:1fRY18cjsHzDgGiJiS2nnpUU3v9JPDc2HNaR7Xk8')
.filter(ee.Filter.eq('Name', 'California'));
// 引入Landsat卫星轨道数据.
var wrs = ee.FeatureCollection('ft:1_RZgjlcqixp-L9hyS6NYGqLaKOlnhSC35AB5M5Ll');
// 定义空间筛选:利用边界进行叠加筛选.
var spatialFilter = ee.Filter.intersects({
leftField: '.geo',
rightField: '.geo',
maxError: 10
});
// 定义SaveAll-Join.
var saveAllJoin = ee.Join.saveAll({
matchesKey: 'scenes',
});
//运用SaveAll-Join.
var intersectJoined = saveAllJoin.apply(cali, wrs, spatialFilter);
// 显示结果.
var intersected = ee.FeatureCollection(ee.List(intersectJoined.first().get('scenes')));
Map.centerObject(cali);
Map.addLayer(intersected, {}, 'WRS-2 polygons');
Map.addLayer(cali, {color: 'FF0000'}, 'California polygon');

【GEE笔记6】数据连接Join_遥感_14

参考资料:

​GEE(Google Earth Engine)学习——常用筛选器Filter操作​​​​第10节 GEE的参数类型 (Filter,Join)​

​Inner Joins​

【GEE笔记6】数据连接Join_数据集_15