如何将含POSIXct日期的数据框转换为时间序列对象?
我有一个包含两列的数据框(DF):第一列为日期,第二列为关注值(VOI)。数据的排列方式比较特殊:先列出1971至2017年所有1月的VOI(共47个数据点),接着是同期所有2月的VOI,以此类推直到12月(同样47个数据点),示例数据如下:
| Date | VOI |
|---|---|
| Jan-1971 | 34 |
| Jan-1972 | 28 |
| Jan-1973 | 29 |
| ... | ... |
| Jan-2017 | 36 |
| Fev-1971 | 48 |
| Fev-1972 | 49 |
| ... | ... |
| Dez-1971 | 15 |
| ... | ... |
| Dez-2017 | 19 |
我用lubridate包的ymd()函数把日期转换成了POSIXct类型,之后尝试用以下代码创建时间序列对象,但都没成功:
ts = xts(x = df$Vazao, order.by = index(df$Date))
ts = xts(x = df$Vazao, order.by = df$Data)
我猜测问题可能出在日期没有按时间顺序排列——我原本以为ymd()能让R识别出正确的时间顺序(从1971年1月、1971年2月……到2017年12月),但显然没达到预期。请问该怎么把这个数据框转换成时间序列对象?
你猜的完全没错!核心问题就是数据框的行没有按时间先后顺序排列——xts要求用于排序的索引必须是严格递增的,乱序的日期会导致创建对象失败或者结果不符合预期。下面是一步步的解决方法:
1. 先把日期格式转对
首先注意:你的日期是Jan-1971这种「月-年」格式,ymd()是处理「年-月-日」的,用错函数可能导致日期转换失败。另外看你的月份缩写是葡萄牙语(比如Fev是二月,Dez是十二月),得先设置对应语言,再用my()函数转换:
library(lubridate) # 根据你的系统设置葡萄牙语环境,Windows和Linux/macOS略有不同 Sys.setlocale("LC_TIME", "pt_PT.UTF-8") # Linux/macOS适用 # Sys.setlocale("LC_TIME", "Portuguese_Brazil.1252") # Windows可选 # 转换日期列 df$Date <- my(df$Date)
转换后可以用class(df$Date)确认一下,应该是Date类型。
2. 按日期对数据框排序
这是最关键的一步,把数据框按Date列从小到大重新排列:
df_sorted <- df[order(df$Date), ]
排序后你可以用head(df_sorted)看看,第一行应该是1971年1月,第二行1971年2月,以此类推,完全符合时间顺序。
3. 创建xts时间序列对象
现在用排序好的数据创建xts对象,注意你之前代码里的Vazao应该是笔误,要对应数据框里的VOI列:
library(xts) ts_xts <- xts(x = df_sorted$VOI, order.by = df_sorted$Date)
备选:用基础R创建ts对象
如果你不需要xts的功能,也可以用基础R的ts()函数——因为你的数据是月度频率,从1971年1月开始,总共有47*12=564个数据点,直接这样创建:
voi_values <- df_sorted$VOI ts_obj <- ts(voi_values, frequency = 12, start = c(1971, 1))
验证结果
创建完成后可以用head(ts_xts)或者plot(ts_xts)来检查,确认时间序列的顺序和数值都正确。
内容的提问来源于stack exchange,提问作者Hugo

