如何用Pandas将300m分辨率土地覆盖数据集降尺度至3000m
300m土地覆盖数据降尺度至3000m的聚合实现方案
一、网格对应关系梳理
3000m是300m的10倍分辨率,每个目标3000m区块对应10×10个原始300m格点。你筛选的1×1度区域中,原始数据每度对应360个300m格点(64800总纬度格数/180度=360,129600总经度格数/360度=360),因此该区域可分成36×36个3000m区块。
二、基于Pandas DataFrame的聚合步骤
假设你的DataFrame命名为df,包含lat、lon、lccs_class列:
1. 给原始格点分配区块ID
通过计算区块经纬度步长,将每个格点映射到所属区块:
# 计算原始300m格点的经纬度间隔 lat_step = df['lat'].diff().dropna().unique()[0] lon_step = df['lon'].diff().dropna().unique()[0] # 3000m区块对应的经纬度步长为原始的10倍 block_lat_step = lat_step * 10 block_lon_step = lon_step * 10 # 生成区块ID:用floor除法完成格点到区块的映射 df['lat_block'] = (df['lat'] - df['lat'].min()) // block_lat_step df['lon_block'] = (df['lon'] - df['lon'].min()) // block_lon_step
2. 聚合主导类并处理多众数情况
按区块分组取lccs_class的众数,同时解决多个类出现次数相同的场景:
def get_dominant_class(series): counts = series.value_counts() max_count = counts.max() # 提取所有出现次数等于最大值的候选类 candidates = counts[counts == max_count].index.tolist() # 选择数值最小的类作为默认结果(可根据业务需求改为随机选或其他规则) return min(candidates) # 按区块分组聚合,得到每个3000m区块的主导类 blocked_result = df.groupby(['lat_block', 'lon_block'])['lccs_class'].agg(get_dominant_class).reset_index()
三、实现“参考周边9个区块”的优化逻辑
若需结合目标区块的8个邻域区块优化多众数判断,可按以下步骤操作:
1. 获取初步区块主导类
# 先通过基础方法得到所有区块的初步结果 blocked_result = df.groupby(['lat_block', 'lon_block'])['lccs_class'].agg(get_dominant_class).reset_index() # 设置索引方便邻域查找 blocked_result = blocked_result.set_index(['lat_block', 'lon_block'])
2. 编写邻域类ilder闸以Frequently区域 [posingXXX原Mar fit库_Lookup,哦不,是邻域类获取函数
def get_neighbor_classes(lat_block, lon_block): # 定义8个邻域的偏移量(上下左右+四个对角) offsets = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)] neighbor_cls = [] for dlat, dlon in offsets: try: cls = blocked_result.loc[(lat_block + dlat, lon_block + dlon), 'lccs_class'] neighbor_cls.append(cls) except KeyError: # 边界区块无对应邻域,直接跳过 continue return neighbor_cls
3. 重新处理多众数区块
# 找出所有存在多众数的区块 def has_multimode(series): counts = series.value_counts() return len(counts[counts == counts.max()]) > 1 multimode_blocks = df.groupby(['lat_block', 'lon_block'])['lccs_class'].apply(has_multimode) multimode_blocks = multimode_blocks[multimode_blocks].index.tolist() # 逐个调整多众数区块的主导类 for lat_block, lon_block in multimode_blocks: # 获取自身的众数候选 self_counts = df[(df['lat_block'] == lat_block) & (df['lon_block'] == lon_block)]['lccs_class'].value_counts() self_candidates = self_counts[self_counts == self_counts.max()].index.tolist() # 获取邻域区块的主导类 neighbor_cls = get_neighbor_classes(lat_block, lon_block) if not neighbor_cls: # 无邻域的边角区块,直接选自身候选中最小的类 final_cls = min(self_candidates) else: # 优先选同时在自身候选和邻域中的类,取邻域中出现次数最多的 neighbor_counts = pd.Series(neighbor_cls).value_counts() common_candidates = [cls for cls in self_candidates if cls in neighbor_counts.index] if common_candidates: final_cls = max(common_candidates, key=lambda x: neighbor_counts[x]) else: # 无共同候选时,仍取自身最小候选(可按需修改规则) final_cls = min(self_candidates) # 更新结果 blocked_result.loc[(lat_block, lon_block), 'lccs_class'] = final_cls # 重置索引得到最终结果 blocked_result = blocked_result.reset_index()
四、更高效的xarray直接聚合方案
若数据量较大,无需转成DataFrame,直接用xarray的coarsen方法效率更高:
import xarray as xr # 假设ds是处理后的xarray数据集,仅保留lccs_class变量 # 按lat和lon方向各取10个格点聚合 coarsened_ds = ds.coarsen(lat=10, lon=10, boundary='trim').agg({'lccs_class': get_dominant_class}) # 如需转成DataFrame blocked_result = coarsened_ds.to_dataframe().reset_index()
内容的提问来源于stack exchange,提问作者DiMi
相关产品推荐
相关产品推荐

