如何用tidyverse正确透视表并修复NOAA的SOI、ONI数据读取错误
NOAA SOI/ONI数据集读取错位问题修复方案
问题根因
你当前的代码存在三个核心错误导致首条记录和官方标注不符:
- 读取数据集时
n_max参数设置过小,截断了前几年的有效数据,SOI直接跳过了1948-1950年的记录,导致首条数据从1951年开始 - 用
filter删除值为-99.99/-99.90的行,这类值是NOAA官方定义的缺测标记,直接删除会导致时间序列行顺序错位 - R语言
substr函数的字符串索引从1开始计数,你写的substr(year, 0, 4)属于不规范写法,部分场景下会出现年份解析错误 - 冗余的手动重构数据框操作会导致列错位,进一步放大数据偏移问题
修复后的完整代码
SOI数据集处理代码
library(tidyverse) library(fpp3) SOI <- read_table("https://psl.noaa.gov/data/correlation/soi.data", skip = 1, n_max = 80, # 放大读取范围覆盖所有已发布年份 col_names = FALSE, na = "-99.99") %>% # 读取时直接将缺测标记转为NA,避免删除行 set_names(c('year', month.abb)) %>% pivot_longer(-year, names_to = 'month', values_to = 'SOI') %>% mutate( year = as.integer(substr(year, 1, 4)), # 修正字符串索引参数 YearMonth = yearmonth(paste(year, month)) ) %>% select(YearMonth, SOI) %>% # 直接选择需要的列,避免手动重构数据框出错 as_tsibble(index = YearMonth) # 验证首条记录 head(SOI, 1)
运行后首条输出将对应1948年1月,SOI值为NA(对应官方标注的-99.99缺测值)。
ONI数据集处理代码
ONI <- read_table("https://psl.noaa.gov/data/correlation/oni.data", skip = 1, n_max = 80, col_names = FALSE, na = "-99.90") %>% set_names(c('year', month.abb)) %>% pivot_longer(-year, names_to = 'month', values_to = 'ONI') %>% mutate( year = as.integer(substr(year, 1, 4)), YearMonth = yearmonth(paste(year, month)) ) %>% select(YearMonth, ONI) %>% as_tsibble(index = YearMonth) # 验证首条记录 head(ONI, 1)
运行后首条输出将对应1950年1月,ONI值为-1.53,和官方标注一致。
核心修正点说明
- 取消
filter删除缺测值的逻辑,改为读取时直接将缺测标记转为NA,保证时间序列的连续性 - 放大
n_max参数取值,避免截断早期年份数据 - 删除冗余的手动数据框重构逻辑,用
select直接筛选需要的列,避免列错位
内容的提问来源于stack exchange,提问作者Rodrigo H. Ozon
相关产品推荐
相关产品推荐

