不同站点时序数据集Sen氏斜率计算及MK检验结果合并问题
解决R分组计算MK检验与Sen氏斜率的报错问题
报错原因说明
- 第一个
summarise无法存入htest对象报错:Mann-Kendall检验、sens.slope返回的结果是htest类型的列表结构,包含统计量、p值、估计值等多个字段,而dplyr的summarise要求每列返回长度为1的原子向量,直接存入整个列表就会触发错误 - 第二个
is.character(x)不成立报错:readr::parse_number()仅支持字符型输入,你要提取的斜率、p值本身就是数值类型,不需要用这个函数做转换,传入数值型参数就会触发类型校验错误
解决代码示例
依赖包
# 用到的依赖包提前加载 library(dplyr) library(Kendall) library(trend)
核心计算逻辑
假设你的数据集命名为site_ts_data,包含site(站点分组字段)、year(时间字段,数值型)、obs_value(待检验的观测值字段),计算并整合两种检验结果的代码如下:
检验结果表 <- site_ts_data %>% # 按站点分组 group_by(site) %>% # 逐组提取检验字段 summarise( # Mann-Kendall检验结果提取 MK_p值 = MannKendall(obs_value)$sl, MK_tau统计量 = MannKendall(obs_value)$tau, # Sen氏斜率结果提取 Sen斜率 = sens.slope(obs_value)$estimate, Sen截距 = sens.slope(obs_value)$intercept, Sen_p值 = sens.slope(obs_value)$p.value, # 分组完成后自动取消分组 .groups = "drop" )
得到的检验结果表就是每个站点对应一行,包含两种检验所有所需指标的结构化数据框。
可选拓展:保留完整检验对象
如果需要留存完整的检验结果供后续调用,可以把检验对象存为列表列:
检验结果表_完整版 <- site_ts_data %>% group_by(site) %>% summarise( MK检验结果 = list(MannKendall(obs_value)), Sen斜率检验结果 = list(sens.slope(obs_value)), .groups = "drop" )
后续需要提取批量指标时,再用mutate+purrr::map从列表列中提取即可。
注意事项
- 每个站点的时间序列需要提前清理缺失值,可在分组前加
drop_na(obs_value)处理 - 若时间序列存在季节波动,需先完成去季节处理再做趋势检验,避免结果失真
- 如果你使用其他包的检验函数,对应字段的提取名要和函数返回的列表结构匹配,比如用
trend::mk.test()的话p值提取逻辑为mk.test(obs_value)$p.value
内容的提问来源于stack exchange,提问作者dudpant
相关产品推荐
相关产品推荐

