R语言突变点检测Mann-Kendall(MK)、滑动平均差等方法

news/2024/11/15 8:40:32/

Move mean滑动平均差法

直接上代码,原理可以看这个文章。

DOI: 10.11821/dlxb201811003

#滑动平均差法
Q <- read.csv("D:/OneDrive/UCAS/stu/2022zdx/zdx_data.csv")
n <- length(Q$Runoff)
p <- 19 #假定时间序列周期Moavse <- function(Q,n,p){MU <- vector(length=n-1)MD <- vector(length=n-1)detaM <- vector(length=n-1)k <- 0for(i in 2:n){if(p>=i-1){k <- i-1}else(k <- p)MU[i] <- 1/k*(sum(Q[c((i-k):(i-1))]))#正向滑动序列if(p>=n-i+1){k <- n-i+1}else(k <- p)MD[i] <- 1/k*(sum(Q[c(i:(i+k-1))]))#逆向滑动序列}detaM <- abs(MU-MD)results <- cbind(MU,MD,detaM)return(results)
}
detaQr <- Moavse(Q$Runoff,n,p)
max3 <- order(detaQr[,3],decreasing=TRUE)[1:3] + 1978plot(x=Q$year,y=detaQr[,3],lty=2,lwd=2,xlab = "time",ylab="deltaM",type="l", col = "blue", ylim = c(-6, 32), main = "Move mean test")
par(new = TRUE)plot(Q$year, Q$Runoff,col="red",lwd=1.5,type="l", xaxt = "n", yaxt = "n", ylim = c(40, 200),ylab = "", xlab = "")
axis(side = 4)
mtext("Runoff", side = 4, line = 1)
legend("topright", c("derltaM", "Runoff"),col = c("blue", "red"), lty = c(1, 2))

由于需要绘制两个轴,设置xaxt和yaxt是为了不显示坐标轴内容,再用mtext手动添加。side是文字的位置(上下左右,4是右面)

image-20221105175337572

如图所示,derltaM取极值的时候认为发生了突变。我把原理稍微画了个图方便理解,如下。该算法主要考虑了周期性,假定周期性前向和后向差距不大,derltaM是前向减去后向,最大值就是突变点了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Siuhk4CI-1667644231215)(https://imagecollection.oss-cn-beijing.aliyuncs.com/img/QQ%E5%9B%BE%E7%89%8720221105175144.jpg)]

Mann Kendall突变检验

参考:http://www.r-china.net/forum.php?mod=viewthread&tid=723

Mann_Kendall <- function(timeserial){#Mann Kendall 突变检验,传递参数Mann_Kendall_sub <- function(timeserial){#需要进行两次秩的分析,因此在函数中嵌套了一个函数r <- c()#分析的三个变量,具体含义可以参照魏凤英老师的书s <- c()#秩序列。U <- c()for(i in 2:length(timeserial))#进行大小比较,从第二个开始与以前的数据进行大小比较{r[i] <- 0for(j in 1:i){if(timeserial[i]>timeserial[j]){r[i] <- r[i]+1}#如果后面的数大于前面的数,则秩加1}s[i] <- 0for (ii in 2:i){s[i] <- s[i] + r[ii]#秩序列。Sk是第i时刻数值大于ii时刻数值个数的累计数}U[i] <- 0U[i] <- (s[i] - (i * (i - 1) / 4))/sqrt(i * (i - 1) * (2 * i + 5) / 72)}r[1] <- 0s[1] <- 0U[1] <- 0LST <- list(r = r, s = s, U = U)return (LST)}timeserial_rev <- rev(timeserial)#生成逆序列y1 <- Mann_Kendall_sub(timeserial)#计算正序列y2 <- Mann_Kendall_sub(timeserial_rev)#计算逆序列y2$U <- -(rev(y2$U))#转换符号与顺序LST <- list(UF=y1,UB=y2)return(LST)  
}Q <- read.csv("D:/OneDrive/UCAS/stu/2022zdx/zdx_data.csv")d <- Mann_Kendall(Q$Runoff)#进行突变检验
yUF <- as.data.frame(d$UF[3])$U
yUB <- as.data.frame(d$UB[3])$Uplot(x=c(1:length(Q$year)),y=yUF, type="l", ylim=c(min(yUF,yUB,-1.96),max(yUF,yUB,1.96)),lwd=1, lty=5, ylab="", cex=0.5,xaxt="n",mgp=c(1,0.1,0),tck=-0.02)
points(x=c(1:length(Q$year)),y=yUB,type="l",lty=3,col=6,lwd=1)
abline(h=1.969,lty=4,lwd=0.5)# 1.969是a=0.05的显著性水平
abline(h=-1.96,lty=4,lwd=0.5)
abline(h=0,col="gray",lwd=0.5)

image-20221105175651915

该方法的原理是:

在构建秩序列后,进而计算累积序列值。当没有突变点时,秩的增长将是自然的并且符合某种分布(如正态分布),这时就可以进行假设性检验。(个人理解,若有不对欢迎指出~)

R包cmp做突变点检验

有现成的R包可以做突变检验,可以使用下列参数:

参考:https://zhuanlan.zhihu.com/p/350235881

ArgumentsCondition
StudentGaussian sequence
BartlettGaussian sequence
GLRGaussian sequence
ExponentialExponentially distributed sequence
GLRAdjusted; ExponentialAdjustedIdentical to the GLR and Exponential statistics
FETBernoulli sequence
Mann-Whitneynon-Gaussian distribution
Moodnon-Gaussian distribution
Lepagenon-Gaussian distribution
Kolmogorov-Smirnovnon-Gaussian distribution
Cramer-von-Misesnon-Gaussian distribution
# library
library(cpm)
cpm.res = processStream(Q$Runoff, cpmType = "Kolmogorov-Smirnov")
# 可视化变点
plot(Q$year, Q$Runoff, type = "l", col = "steelblue", lwd = 2)
abline(v = cpm.res$changePoints + 1978, lwd = 3.5, col = "red")
# 变点坐标信息提取
print(cpm.res$changePoints)

image-20221105180231023

lblue", lwd = 2)
abline(v = cpm.res$changePoints + 1978, lwd = 3.5, col = “red”)

变点坐标信息提取

在这里插入图片描述

完整的代码和数据在后台发送【R突变】就可以获得了


http://www.ppmy.cn/news/376375.html

相关文章

利用Matlab实现Mann-Kendall(MK)突变检验函数

利用Matlab实现Mann-Kendall&#xff08;MK&#xff09;突变检验函数 一、MK突变检验 1、一般取显著性水平α0.05&#xff0c;那么临界值U0.05 1.96 。将UFk和UBk两个统计量序列曲线和1.96 两条直线均绘在一张图上。 2、若UFk和UBk的值大于0&#xff0c;则表明序列呈上升趋势&…

Linux下 man命令的使用 及 中文man手册的安装

文章目录 1. man命令使用2. 安装中文man手册 1. man命令使用 man命令是Linux下最核心的命令之一。而man命令也并不是英文单词“man”的意思&#xff0c;它是单词manual的缩写&#xff0c;即使用手册的意思。man命令会列出一份完整的说明。其内容包括命令语法、各选项的意义及相…

Theil-Sen Median斜率估计和Mann-Kendall趋势分析:以多年NPP数据为例

一、理论 Theil-Sen Median方法又称为Sen斜率估计&#xff0c;是一种稳健的非参数统计的趋势计算方法。该方法计算效率高&#xff0c;对于测量误差和利群数据不敏感&#xff0c;适用于长时间序列数据的趋势分析。其计算公式为&#xff1a; Mann-Kendall(MK)检验是一种非参数…

基于 Python 的 M-K(Mann-Kendall)突变检验 的简单实现

M-K&#xff08;Mann-Kendall&#xff09;法是一种气候诊断与预测技术&#xff0c;可以判断气候序列中是否存在气候突变&#xff0c;如果存在&#xff0c;可确定出突变发生的时间。Mann-Kendall检验法也经常用于气候变化影响下的降水、干旱频次趋势检测。由于最初由曼(H.B.Mann…

8.16 记忆增强神经网络:MANN、神经网络图灵机

文章目录 1.神经网络图灵机前言读记忆 (Read Heads)写记忆(Write Heads)寻址机制基于内容的寻址基于位置的寻址Interpolation(插值)convolution shift(卷积偏移)Sharping(重塑)控制网络总结2、记忆增强神经网络2.1、读记忆2.2 写记忆参考👉8.7 Meta learning元学习全面理解、…

什么是点阵液晶屏和段码液晶屏

液晶屏的叫法非常多样&#xff0c;主要分为点阵液晶屏和段码液晶屏&#xff0c;今天我们就来聊聊这两类的区别在哪。 点阵液晶屏是依照一定的标准排序起來的阵列&#xff0c;比较普遍的是图型点阵lcd屏模组。点阵液晶屏是由许多个显示点(等同于显示器的一个清晰度)构成的&…

点阵液晶屏和段码液晶屏有何区别

液晶屏的叫法非常多样&#xff0c;主要分为点阵液晶屏和段码液晶屏&#xff0c;今天我们就来聊聊这两类的区别在哪。 ​ 点阵液晶屏是依照一定的标准排序起來的阵列&#xff0c;比较普遍的是图型点阵lcd屏模组。点阵液晶屏是由许多个显示点(等同于显示器的一个清晰度)构成的&a…

网口基本知识

网口扫盲一:网卡初步认识 网络适配器又称网卡或网络接口卡(NIC),英文名Network Interface Card.它是使计算机联网的设备.平常所说的网卡就是将PC机和LAN连接的网络适配器.网卡(NIC) 插在计算机主板插槽中,负责将用户要传递的数据转换为网络上其它设备能够识别的格式,通过网络介…