长时序栅格数据缺失值插补

news2024/11/17 11:54:48

长时序栅格数据经常会出现一些缺失值,会对后续的分析造成很大的不便。这便需要利用一些插值算法对这些缺失数据进行填补,奇异谱分析(SSA)便是常用的一种插值方法。更多内容可见公众号GeodataAnalysis

简介

在时间序列分析中,「奇异谱分析」「SSA」)是一种非参数谱估计方法。它结合了经典时间序列分析、多元统计、多元几何、动力系统和信号处理的元素。

  • “奇异谱分析”这个名称涉及协方差矩阵的奇异值分解中的特征值谱,而不是直接涉及频域分解。

  • SSA 可以帮助分解时间序列分解为组件的总和,每个组件都有有意义的解释。如下图所示,奇异谱分析分解出来了趋势、变化和噪声三部分。

  • SSA只考虑数据本身的特征,不考虑其他因素,特别适合于插补、平稳时间序列的预测。

SSA填补缺失值

导入所需的第三方库

import os
import calendar
import numpy as np
import rasterio as rio

import pandas as pd
from mssa.mssa import mSSA
import matplotlib.pyplot as plt

生成测试数据

x = np.arange(365)
y = np.sin(x * np.pi * 2 / 365) + np.random.randn(x.size) * 0.2

y[:5] = np.nan
y[-30:] = np.nan
y[90:95] = np.nan
y[200:205] = np.nan
y[300:305] = np.nan

plt.plot(x, y);

SSA插补

df = pd.DataFrame(data=y, columns=['data'])
model = mSSA(rank=None, fill_in_missing = True)
model.update_model(df)

df2 = model.predict('data', 0, df.shape[0]-1)

mask = np.isnan(y)
plt.plot(x, y)
plt.scatter(x[mask], pred[mask], c='r', s=1);

通过分析预测结果可知,时间序列的末尾若缺失值超过十个,最后五个的缺失值便无法预测。这里采用的解决办法为,用预测值再进行预测。具体代码如下:

def fill_value(data):
    def _fill_value(data):
        df = pd.DataFrame(data=data, columns=['data'])
        model = mSSA(rank=None, fill_in_missing = True)
        model.update_model(df)

        df2 = model.predict('data', 0, df.shape[0]-1)
        pred = df2.loc[:, 'Mean Predictions'].values

        return pred

    pred = _fill_value(data)
    while True:
        mask = np.isnan(pred)
        if np.any(mask):
            pred2 = _fill_value(pred)
            pred[mask] = pred2[mask]
        else:
            break
    return pred
pred = fill_value(y)

mask = np.isnan(y)
plt.plot(x, y);
plt.plot(x, pred);
plt.scatter(x[mask], pred[mask], c='r', s=3);

栅格数据插补

获取所有数据的路径

数据保存格式如下:

data
	20170101.tif
	20170102.tif
	··· ···
	20171231.tif
paths = []
years = [2017]
months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
root_dir = './data'

for year in years:
    for month in months:
        day_num = calendar.monthrange(year, int(month))[1]
        for day in range(1, day_num+1):
            path = f'{root_dir}/{year}{month}%02d.tif' % day
            paths.append(path)

读取所有栅格数据

若某个栅格数据不存在,则将其视为全部是缺失值。

def check_data(paths):
    '''检查所有数据文件是否横列数全部相同,同时返回其行列数'''
    # 以第一个路径为基准
    src = rio.open(paths[0])
    RasterXSize, RasterYSize = src.width, src.height
    gt = src.transform
    proj = src.crs
    for i in range(1, len(paths)):
        if not os.path.exists(paths[i]):
            continue
        src = rio.open(paths[i])
        assert RasterXSize == src.width
        assert RasterYSize == src.height
        assert gt == src.transform
        assert proj == src.crs
    info = {
	    'RasterXSize': RasterXSize, 
	    'RasterYSize': RasterYSize, 
	    'shape': (RasterXSize, RasterYSize), 
	    'gt': gt, 
	    'proj': proj
    }
    return info

def rasters_to_array(paths, band_num=1, win=None):
    '''读取所有数据文件,并转换为Numpy数组输出'''
    data_info = check_data(paths)
    for i in range(len(paths)):
        path = paths[i]
        if os.path.exists(path):
            # 读取数据
            src = rio.open(path)
            array = src.read(band_num, window=win)
            # 设置数据的NoData值
            nodata = src.nodata
            array[array==nodata] = np.nan
        else:
            # 若第一个路径为空,可自行设置数据类型
            array = np.full(shape=(data_info['RasterYSize'], data_info['RasterXSize']), 
                            fill_value=np.nan, dtype=array.dtype)
        # 拼接数组
        if 0 == i:
            out_array = array[np.newaxis, :, :]
        else:
            out_array = np.concatenate((out_array, array[np.newaxis, :, :]), axis=0)
    return out_array, data_info
array, data_info = rasters_to_array(paths)

栅格数据插补

def array_to_tif(out_path, arr, crs, transform, nodata=None):
    # 获取数组的形状
    if arr.ndim==2:
        count = 1
        height, width = arr.shape
    elif arr.ndim==3:
        count = arr.shape[0]
        _, height, width = arr.shape
    else:
        raise ValueError
    
    with rio.open(out_path, 'w', 
                  driver='GTiff', 
                  height=height, width=width, 
                  count=count, 
                  dtype=arr.dtype, 
                  crs=crs, 
                  transform=transform, 
                  nodata=nodata) as dst:
        # 写入数据到输出文件
        if count==1:
            dst.write(arr, 1)
        else:
            for i in range(count):
                dst.write(arr[i, ...], i+1)
fill_array = array.copy()
# 最大缺失值数量
thre = 65

for i in range(array.shape[1]):
    for j in range(array.shape[2]):
        data = array[:, i, j]
        mask = np.isnan(data)
        if np.all(mask):
            continue
        if np.count_nonzero(mask)>thre:
            continue
        index = np.arange(data.size)
        pred = fill_value(data)

        fill_array[index, i, j] = pred
out_dir = './results'

for i, path in enumerate(paths):
    file_name = os.path.basename(path)
    out_path = os.path.join(out_dir, file_name)
    array_to_tif(out_path, fill_array[i, ...], 
                 data_info['proj'], data_info['gt'], 
                 nodata=np.nan)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1060183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

处理机调度的概念,层次联系以及七状态模型

1.基本概念 当有一堆任务要处理,但由于资源有限,这些事情没法同时处理。 这就需要确定某种规则来决定处理这些任务的顺序,这就是“调度”研究的问题。 2. 三个层次 1.高级调度(作业调度) 高级调度(作业…

websocket逆向【python实现websocket拦截】

python实现websocket拦截 前言一、拦截的优缺点优点:缺点:二、实现方法1.环境配置2.代码三、总结前言 开发者工具F12,筛选ws后,websocket的消息是这样显示的,如何获取这里面的消息呢? 以下是本篇文章正文内容 一、拦截的优缺点 主要讲解一下websocket拦截的实现,现在…

结构和基本尺寸

声明 本文是学习GB-T 586-2015 船用法兰铸钢止回阀. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了法兰连接尺寸和密封面按 CB/T 4196、GB/T 2501 的船用法兰铸钢止回阀(以下简 称止回阀)的分类和标记、要求、试验方法、检验规…

sheng的学习笔记-【中英】【吴恩达课后测验】Course 1 - 神经网络和深度学习 - 第四周测验

课程1_第4周_测验题 目录:目录 第一题 1.在我们的前向传播和后向传播实现中使用的 “缓存” 是什么? A. 【  】它用于在训练期间缓存成本函数的中间值。 B. 【  】我们用它将在正向传播过程中计算的变量传递到相应的反向传播步骤。它包含了反向传…

Linux系统编程系列之条件变量

一、什么是条件变量 条件变量是一种同步互斥机制,通常与互斥锁一起使用以实现线程之间的通信和同步。 二、问题的引入 先来看一个例子:小楠是一名在校学生,每个月都会从父母那里得到一笔生活费。现在她的钱花光了,想要去取钱。但是很显然取钱…

Redis-缓存穿透,缓存击穿,缓存雪崩

缓存穿透,缓存击穿,缓存雪崩 缓存穿透处理方案解决方案1 缓存空数据解决方案2 布隆过滤器 缓存击穿处理方案解决方案 1 互斥锁解决方案2 逻辑过期 缓存雪崩处理方案解决方案 1 给不同的key的过期时间设置添加一个随机值,降低同一个时段大量ke…

柯桥生活口语学习,英语中初次见面,除了Nice to meet you,还能说什么?

第一印象非常重要。所以当你第一次见到某人时,留下一个好印象很重要,尤其是当你面对一个重要的工作或者面对某个对你来说可能非常特别的人时。 下面我列出了一些最常用的说“很高兴见到你”的表达方法,也包括对方的回答,除了nice …

活动报名与缴费小程序开发笔记一

项目背景 活动报名与缴费小程序的开发背景主要源于以下几个因素: 1.数字化时代的需求: 随着移动互联网和智能手机的普及,人们习惯使用手机进行各种活动。传统的纸质报名表格和线下缴费方式变得相对繁琐,而数字化报名与缴费小程序…

2023年-华为机试题库B卷(Python)【满分】

华为机试题库B卷 已于5月10号 更新为2023 B卷 (2023-10-04 更新本文) 华为机试有三道题目,前两道属于简单或中等题,分值为100分,第三道为中等或困难题,分值为200分。总分为 400 分,150分钟考试…

GKR+Groth16:更快的MiMC证明

1. 引言 Consensys团队Alexandre Belling等人2022年论文 Recursion over Public-Coin Interactive Proof Systems; Faster Hash Verification 中,提出了: 用GKR来证明MiMC哈希计算的完整性将GKR verifier嵌入到SNARK(Groth16)电…

【开发篇】十四、SpringBoot整合Quartz实现定时任务

文章目录 1、关于定时任务2、Java原生实现3、相关名词4、SpringBoot整合Quartz5、Quartz的通用配置6、关于QuartzJobBean7、关于调度器Scheduler的绑定8、Quartz持久化 1、关于定时任务 定时任务在实际开发中使用场景很多,比如: 年度报告各种统计报告某…

vs code 离线安装 CodeLLDB 包[Acquiring CodeLLDB platform package]

1. 问题描述 最近在配置使用vscode编译c,一打开vscode就弹出以下信息“Acquiring CodeLLDB platform package” 2. 问题原因 vscode在安装CodeLLDB插件时,速度太慢,一直不能成功 3. 解决方案: 离线下载 CodeLLDB插件&#xff0c…

前后端通信到底是怎样一个过程

前后端通信是怎样 前言:Http协议 超文本传输协议 规定:每一次前后端通信,前端需要主动向后端发出请求,后端接收到前端的请求后,可以给出响应 1、Http报文 浏览器向服务器发送请求时,请求本身就是信息&…

ROS导航——环境感知(激光雷达)

下载相关驱动包(激光雷达厂商应该会给出) 编译后可能会出现部分错误,以下是部分情况: (1) 移植功能包后出现c文件无法找到头文件的情况:解决链接 修改代码:(以我的雷达为…

将pyc文件转换为py文件

1.首先将pip版本升级 pip install --upgrade pip 2.然后安装uncompyle6 pip install uncompyle6 3.在系统的环境变量中,添加“python_home” 4.在系统变量Path中添加: %python_home%\Scripts\ 5.运行下面的代码,就会在你.pyc对应文件夹…

腾讯云服务器完整建站过程(新手搭建网站教程)

使用腾讯云服务器搭建网站全流程,包括轻量应用服务器和云服务器CVM建站教程,轻量可以使用应用镜像一键建站,云服务器CVM可以通过安装宝塔面板的方式来搭建网站,腾讯云服务器网分享使用腾讯云服务器建站教程,新手站长搭…

第二章 进程与线程 十九、管程

目录 一、定义 管程是一种特殊的软件模块,由以下部分组成: 二、管程的基本特征 三、使用管程解决生产者消费者问题 四、总结 一、定义 管程是一种特殊的软件模块,由以下部分组成: 1、局部于管程的共享数据结构说明;&#xf…

[QT编程系列-45]: 内存检测工具Dr.Memory在Windows上的使用实践与详解

目录 一、使用前的澄清 二、下载地址 三、功能概述 四、 使用方法与步骤 4.1 常见命令 4.2 命令选项详解 4.3 常见问题监测 4.3.1 内存泄露相关参数 4.4 结果输出参数 4.5 输出分析 一、使用前的澄清 (1)之前在https://blog.csdn.net/fengbin…

SNAP与Sen2Cor下载与安装

SNAP软件下载与安装 一、下载地址 首先进入网站 找到DOWNLOAD下载页, 安装完成后,界面如下 还需要再装一个Sen2cor下载好之后,解压到用户文件夹下 然后打开L2A_Process.bat文件 打开CMD,输入 cd C:\Users\lenovo\AppData\L…