R语言入门学习教程,从入门到精通,R语言日期和时间序列(6)

R语言日期和时间序列


一、日期和时间函数

1. 返回系统当前日期和时间

主要函数

  • Sys.Date():返回当前日期
  • Sys.time():返回当前日期和时间
  • date():返回当前日期和时间(字符串格式)

案例代码

r 复制代码
# 获取当前日期(Date对象)
current_date <- Sys.Date()
print(current_date)  # 输出类似 "2026-04-29"

# 获取当前日期和时间(POSIXct对象)
current_datetime <- Sys.time()
print(current_datetime)  # 输出类似 "2026-04-29 14:30:25"

# 获取当前日期和时间(字符串格式)
current_datetime_str <- date()
print(current_datetime_str)  # 输出类似 "Wed Apr 29 14:30:25 2026"

2. 时间函数 as.POSIXlt() 和 as.POSIXct()

说明

  • POSIXct:从1970年1月1日开始的秒数,适合存储和计算
  • POSIXlt:列表形式,包含年、月、日、时、分、秒等独立成分

案例代码

r 复制代码
# 创建一个时间字符串
time_str <- "2026-04-29 15:30:00"

# 转换为POSIXct格式(连续时间)
time_ct <- as.POSIXct(time_str)
print(time_ct)  # 输出 "2026-04-29 15:30:00"
class(time_ct)  # 查看类型:"POSIXct" "POSIXt"

# 转换为POSIXlt格式(列表时间)
time_lt <- as.POSIXlt(time_str)
print(time_lt)  # 输出 "2026-04-29 15:30:00"
class(time_lt)  # 查看类型:"POSIXlt" "POSIXt"

# 从POSIXlt中提取各个成分
print(paste("年:", time_lt$year + 1900))   # 年份需要加1900
print(paste("月:", time_lt$mon + 1))       # 月份从0开始,需要加1
print(paste("日:", time_lt$mday))
print(paste("时:", time_lt$hour))
print(paste("分:", time_lt$min))
print(paste("秒:", round(time_lt$sec)))
print(paste("星期几(0-6,0=周日):", time_lt$wday))
print(paste("一年中的第几天:", time_lt$yday))

二、日期格式转换

1. as.Date() 函数

语法

r 复制代码
as.Date(x, format = "输入格式")

常见格式代码

  • %Y:4位数年份(2026)
  • %y:2位数年份(26)
  • %m:月份(01-12)
  • %d:日期(01-31)
  • %B:完整月份名(January)
  • %b:缩写月份名(Jan)

案例代码

r 复制代码
# 不同格式的日期字符串
date1 <- "2026-04-29"
date2 <- "04/29/2026"
date3 <- "29Apr2026"
date4 <- "2026年4月29日"

# 转换为Date对象(需要指定输入格式)
d1 <- as.Date(date1)                    # 标准格式,无需指定
d2 <- as.Date(date2, format = "%m/%d/%Y")
d3 <- as.Date(date3, format = "%d%b%Y")
d4 <- as.Date(date4, format = "%Y年%m月%d日")

print(d1); print(d2); print(d3); print(d4)
print(class(d1))  # 输出 "Date"

2. format() 函数

语法

r 复制代码
format(日期对象, format = "输出格式")

案例代码

r 复制代码
# 创建一个日期对象
my_date <- as.Date("2026-04-29")

# 以不同格式输出
print(format(my_date, format = "%Y年%m月%d日"))       # 2026年04月29日
print(format(my_date, format = "%B %d, %Y"))         # April 29, 2026
print(format(my_date, format = "%a %b %d"))          # Wed Apr 29
print(format(my_date, format = "%Y-%m-%d"))          # 2026-04-29
print(format(my_date, format = "%y/%m/%d"))          # 26/04/29
print(format(my_date, format = "%j"))                # 一年中的第119天
print(format(my_date, format = "%A"))                # 星期三(完整星期名)

三、其他函数

常用函数

  • weekdays():返回星期几
  • months():返回月份名称
  • quarters():返回季度
  • julian():返回从原点开始的天数

案例代码

r 复制代码
# 创建日期对象
dt <- as.Date("2026-04-29")

# 提取信息
print(weekdays(dt))   # 输出 "星期三"
print(months(dt))     # 输出 "四月"
print(quarters(dt))   # 输出 "Q2"(第二季度)

# 计算儒略日(从1970-01-01开始的天数)
julian_days <- julian(dt)
print(julian_days)    # 输出类似 "20578"

# 从数字创建日期(从1970-01-01开始的天数)
origin_date <- as.Date(0, origin = "1970-01-01")
print(origin_date)    # 输出 "1970-01-01"

四、生成日期时间

1. 生成日期序列

使用 seq() 函数

r 复制代码
# 生成连续日期序列
start_date <- as.Date("2026-01-01")
end_date <- as.Date("2026-01-10")

# 按天生成
daily_seq <- seq(start_date, end_date, by = "day")
print(daily_seq)

# 按周生成
weekly_seq <- seq(start_date, end_date, by = "week")
print(weekly_seq)

# 按月生成
monthly_seq <- seq(start_date, as.Date("2026-12-01"), by = "month")
print(monthly_seq)

# 指定长度生成
len_seq <- seq(start_date, by = "2 days", length.out = 10)
print(len_seq)

2. 生成时间序列

案例代码

r 复制代码
# 生成时间点序列(精确到小时)
start_time <- as.POSIXct("2026-04-29 08:00:00")
end_time <- as.POSIXct("2026-04-29 18:00:00")

# 按小时生成
hourly_seq <- seq(start_time, end_time, by = "hour")
print(hourly_seq)

# 按30分钟生成
min30_seq <- seq(start_time, end_time, by = "30 min")
print(min30_seq)

# 按指定数量生成
time_seq <- seq(start_time, by = "3 hours", length.out = 8)
print(time_seq)

3. 创建时间序列对象

使用 ts() 函数

r 复制代码
# 创建时间序列对象
# 参数:数据,起始时间,频率(12=月度,4=季度,1=年度)
data <- c(100, 120, 115, 130, 145, 140)

# 年度数据(从2020年开始)
ts_yearly <- ts(data, start = 2020, frequency = 1)
print(ts_yearly)

# 季度数据(从2020年第1季度开始)
ts_quarterly <- ts(data, start = c(2020, 1), frequency = 4)
print(ts_quarterly)

# 月度数据(从2020年1月开始)
ts_monthly <- ts(data, start = c(2020, 1), frequency = 12)
print(ts_monthly)

# 查看时间序列属性
print(start(ts_monthly))  # 起始时间
print(end(ts_monthly))    # 结束时间
print(frequency(ts_monthly))  # 频率

五、日期时间运算

1. 日期直接相减

案例代码

r 复制代码
# 创建两个日期
date_start <- as.Date("2026-04-29")
date_end <- as.Date("2026-05-20")

# 直接相减计算天数差
date_diff <- date_end - date_start
print(date_diff)        # 输出 Time difference of 21 days
print(as.numeric(date_diff))  # 输出 21(纯数字)

# 计算年龄示例
birthday <- as.Date("1990-05-15")
today <- Sys.Date()
age_days <- today - birthday
age_years <- as.numeric(age_days) / 365.25
print(paste("年龄:", round(age_years, 1), "岁"))

2. 使用 difftime() 函数

语法

r 复制代码
difftime(time1, time2, units = "单位")

单位选项"auto", "secs", "mins", "hours", "days", "weeks"

案例代码

r 复制代码
# 创建时间点
time1 <- as.POSIXct("2026-04-29 14:00:00")
time2 <- as.POSIXct("2026-04-30 16:30:00")

# 计算不同单位的时间差
diff_days <- difftime(time2, time1, units = "days")
diff_hours <- difftime(time2, time1, units = "hours")
diff_mins <- difftime(time2, time1, units = "mins")
diff_secs <- difftime(time2, time1, units = "secs")

print(paste("天数差:", diff_days))
print(paste("小时差:", diff_hours))
print(paste("分钟差:", diff_mins))
print(paste("秒数差:", diff_secs))

# 时间差计算的实际应用
start_work <- as.POSIXct("2026-04-29 09:00:00")
end_work <- as.POSIXct("2026-04-29 17:30:00")
work_hours <- difftime(end_work, start_work, units = "hours")
print(paste("今天工作时间:", work_hours, "小时"))

六、lubridate 包(推荐使用)

安装和加载

r 复制代码
# 安装包(如未安装)
# install.packages("lubridate")

# 加载包
library(lubridate)

1. 提取日期和时间

案例代码

r 复制代码
# 创建日期时间对象
now_time <- now()  # 当前时间
print(now_time)

# 提取各个成分
print(paste("年:", year(now_time)))
print(paste("月:", month(now_time)))
print(paste("月(中文):", month(now_time, label = TRUE, abbr = FALSE)))
print(paste("日:", day(now_time)))
print(paste("时:", hour(now_time)))
print(paste("分:", minute(now_time)))
print(paste("秒:", second(now_time)))
print(paste("星期几:", wday(now_time, label = TRUE)))
print(paste("一年中的第几天:", yday(now_time)))
print(paste("季度:", quarter(now_time)))

2. 解析日期和时间

案例代码

r 复制代码
# 自动解析多种格式
d1 <- ymd("2026-04-29")           # 年月日
d2 <- mdy("04/29/2026")           # 月日年
d3 <- dmy("29-04-2026")           # 日月年
d4 <- ymd_hms("2026-04-29 15:30:45")  # 年月日时分秒
d5 <- mdy_hm("04/29/2026 03:45 PM")   # 带上下午

print(d1); print(d2); print(d3)
print(d4); print(d5)

# 解析不规范的日期字符串
date_str <- c("20260429", "2026/04/29", "29-Apr-2026")
parsed_dates <- ymd(date_str)  # 自动识别常见格式
print(parsed_dates)

3. 时间日期计算

案例代码

r 复制代码
# 创建基准日期
base_date <- ymd("2026-04-29")

# 日期加减运算
print(base_date + days(10))      # 加10天
print(base_date + weeks(2))      # 加2周
print(base_date + months(3))     # 加3个月
print(base_date + years(1))      # 加1年
print(base_date - days(5))       # 减5天

# 滚动到指定日期
print(floor_date(base_date, "month"))   # 当月第一天
print(ceiling_date(base_date, "month")) # 下月第一天
print(floor_date(base_date, "year"))    # 当年第一天

# 计算两个日期之间的跨度
date1 <- ymd("2026-01-15")
date2 <- ymd("2026-12-31")

# 计算间隔
interval_days <- date2 - date1
print(paste("相差天数:", interval_days))

# 使用interval和time_length
time_span <- interval(date1, date2)
print(paste("相差天数:", time_length(time_span, "days")))
print(paste("相差周数:", time_length(time_span, "weeks")))
print(paste("相差月数:", time_length(time_span, "months")))
print(paste("相差年数:", time_length(time_span, "years")))

4. 时间间隔

案例代码

r 复制代码
# 创建间隔
start <- ymd_hms("2026-04-29 09:00:00")
end <- ymd_hms("2026-04-29 17:00:00")

# 创建间隔对象
work_interval <- interval(start, end)
print(work_interval)

# 检查某个时间是否在间隔内
check_time <- ymd_hms("2026-04-29 12:30:00")
is_within <- check_time %within% work_interval
print(paste("12:30是否在工作时间内:", is_within))

# 合并间隔
int1 <- interval(ymd("2026-01-01"), ymd("2026-01-31"))
int2 <- interval(ymd("2026-02-01"), ymd("2026-02-28"))
int_union <- union(int1, int2)
print(int_union)

# 判断间隔是否重叠
int3 <- interval(ymd("2026-01-15"), ymd("2026-02-15"))
int_overlap <- intersect(int1, int3)
print(int_overlap)

5. 时区的操作

案例代码

r 复制代码
# 查看当前时区
current_tz <- Sys.timezone()
print(paste("当前时区:", current_tz))

# 创建带时区的时间
time_utc <- now(tzone = "UTC")
time_shanghai <- now(tzone = "Asia/Shanghai")
time_newyork <- now(tzone = "America/New_York")

print(paste("UTC时间:", time_utc))
print(paste("上海时间:", time_shanghai))
print(paste("纽约时间:", time_newyork))

# 时区转换
original_time <- ymd_hms("2026-04-29 14:00:00", tz = "Asia/Shanghai")
converted_time <- with_tz(original_time, tzone = "America/New_York")
print(paste("上海时间(14:00)等于纽约时间:", converted_time))

# 强制修改时区(不改变时间数值)
forced_time <- force_tz(original_time, tzone = "UTC")
print(paste("强制设为UTC:", forced_time))

七、zoo 包(时间序列基础包)

安装和加载

r 复制代码
# install.packages("zoo")
library(zoo)

1. 创建时间序列

案例代码

r 复制代码
# 准备数据
data_values <- c(10, 15, 13, 18, 20, 22)
dates <- as.Date(c("2026-01-01", "2026-01-02", "2026-01-03", 
                   "2026-01-04", "2026-01-05", "2026-01-06"))

# 创建zoo对象
zoo_ts <- zoo(data_values, order.by = dates)
print(zoo_ts)

# 查看属性和结构
print(class(zoo_ts))
print(index(zoo_ts))   # 查看时间索引
print(coredata(zoo_ts)) # 查看核心数据

# 创建不规则时间序列
irregular_dates <- as.Date(c("2026-01-01", "2026-01-03", "2026-01-10", "2026-02-01"))
irregular_data <- c(100, 150, 200, 180)
zoo_irregular <- zoo(irregular_data, order.by = irregular_dates)
print(zoo_irregular)

2. 类型转换

案例代码

r 复制代码
# 创建示例zoo对象
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
values <- rnorm(10, mean = 100, sd = 10)
zoo_obj <- zoo(values, order.by = dates)

# zoo转数据框
df <- data.frame(date = index(zoo_obj), value = coredata(zoo_obj))
print(head(df))

# zoo转ts(需要规则时间序列)
# 先合并成规则序列
regular_zoo <- merge(zoo_obj, zoo(, seq(start(zoo_obj), end(zoo_obj), by = "day")))
ts_obj <- as.ts(regular_zoo)
print(ts_obj)

# zoo转xts(需要xts包)
# library(xts)
# xts_obj <- as.xts(zoo_obj)

3. 数据操作

案例代码

r 复制代码
# 创建示例数据
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
values <- c(10, 15, NA, 18, 20, NA, 23, 25, 27, 30)
zoo_obj <- zoo(values, dates)

# 处理缺失值 - 线性插值
zoo_na_interp <- na.approx(zoo_obj)
print("插值后的数据:")
print(zoo_na_interp)

# 向前填充缺失值
zoo_na_locf <- na.locf(zoo_obj)
print("向前填充后的数据:")
print(zoo_na_locf)

# 删除缺失值
zoo_na_omit <- na.omit(zoo_obj)
print("删除缺失值后的数据:")
print(zoo_na_omit)

# 滚动计算(移动平均)
zoo_ma <- rollmean(zoo_obj, k = 3, fill = NA)
print("3期移动平均:")
print(zoo_ma)

# 滚动求和
zoo_sum <- rollsum(zoo_obj, k = 3, fill = NA)
print("3期滚动求和:")
print(zoo_sum)

# 差分运算
zoo_diff <- diff(zoo_obj)
print("一阶差分:")
print(zoo_diff)

# 滞后
zoo_lag <- lag(zoo_obj, k = 1)
print("滞后一期:")
print(zoo_lag)

八、xts 包(时间序列扩展包)

安装和加载

r 复制代码
# install.packages("xts")
library(xts)

1. 创建时间序列

案例代码

r 复制代码
# 准备数据
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
data_matrix <- matrix(1:20, ncol = 2)

# 创建xts对象
xts_obj <- xts(data_matrix, order.by = dates)
print(xts_obj)

# 命名列
colnames(xts_obj) <- c("Value1", "Value2")
print(xts_obj)

# 使用日期时间(精确到分钟)
minute_dates <- seq(as.POSIXct("2026-04-29 09:00:00"), 
                    as.POSIXct("2026-04-29 17:00:00"), 
                    by = "30 min")
minute_data <- rnorm(length(minute_dates), mean = 100, sd = 5)
xts_minute <- xts(minute_data, order.by = minute_dates)
print(head(xts_minute))

2. xts 包的基本操作

案例代码

r 复制代码
# 创建示例xts对象
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
data <- data.frame(
  price = round(runif(10, 100, 200), 2),
  volume = round(runif(10, 1000, 5000))
)
xts_obj <- xts(data, order.by = dates)

# 查看数据
print(first(xts_obj))      # 查看前6行
print(last(xts_obj))       # 查看后6行
print(head(xts_obj, 3))    # 查看前3行
print(tail(xts_obj, 3))    # 查看后3行

# 索引操作
print(index(xts_obj))      # 提取时间索引
print(coredata(xts_obj))   # 提取核心数据

# 按时间范围子集
print(xts_obj["2026-01-03/2026-01-06"])      # 日期范围子集
print(xts_obj["2026-01-05"])                  # 单个日期

# 使用逻辑索引
print(xts_obj[xts_obj$price > 150])            # 价格大于150的行

3. 按时间统计数据

案例代码

r 复制代码
# 创建完整月度数据
dates_monthly <- seq(as.Date("2026-01-01"), as.Date("2026-12-31"), by = "day")
monthly_data <- xts(runif(length(dates_monthly), 50, 150), order.by = dates_monthly)

# 按月汇总
monthly_avg <- apply.monthly(monthly_data, mean)    # 每月平均值
monthly_sum <- apply.monthly(monthly_data, sum)     # 每月总和
monthly_max <- apply.monthly(monthly_data, max)     # 每月最大值

print(head(monthly_avg))
print(head(monthly_sum))

# 按季度汇总
quarterly_avg <- apply.quarterly(monthly_data, mean)
print(quarterly_avg)

# 按年汇总
yearly_avg <- apply.yearly(monthly_data, mean)
print(yearly_avg)

# 按周汇总
weekly_avg <- apply.weekly(monthly_data, mean)
print(head(weekly_avg))

# 自定义周期(每3天)
period.apply(monthly_data, endpoints(monthly_data, on = "days", k = 3), mean)

4. 更改时间周期

案例代码

r 复制代码
# 创建高频时间序列(小时级)
hours <- seq(as.POSIXct("2026-04-29 00:00:00"), 
             as.POSIXct("2026-04-29 23:00:00"), 
             by = "hour")
high_freq_data <- xts(rnorm(length(hours), 100, 10), order.by = hours)

# 转换为日数据(降采样)
daily_data <- to.daily(high_freq_data)
print(daily_data)

# 转换为周期性数据
period.apply(high_freq_data, endpoints(high_freq_data, on = "hours", k = 6), mean)

# 升采样(从日数据到小时数据)
daily_dates <- seq(as.Date("2026-04-01"), as.Date("2026-04-05"), by = "day")
daily_values <- xts(1:5, order.by = daily_dates)

# 创建小时级别的时间索引
hourly_index <- seq(as.POSIXct("2026-04-01 00:00:00"), 
                    as.POSIXct("2026-04-05 23:00:00"), 
                    by = "hour")

# 合并并向前填充
hourly_values <- merge(daily_values, xts(, hourly_index))
hourly_filled <- na.locf(hourly_values)
print(head(hourly_filled, 10))

# 使用align.time对齐时间
aligned <- align.time(high_freq_data, n = 60*60)  # 对齐到整点
print(head(aligned))

九、综合案例

案例1:股票数据分析(完整流程)

r 复制代码
# 加载所需包
library(lubridate)
library(xts)

# 创建模拟股票数据
set.seed(123)
dates <- seq(as.Date("2026-01-01"), as.Date("2026-03-31"), by = "day")
n <- length(dates)

# 生成模拟数据
stock_data <- data.frame(
  date = dates,
  open = round(runif(n, 100, 110), 2),
  high = round(runif(n, 105, 115), 2),
  low = round(runif(n, 95, 105), 2),
  close = round(runif(n, 100, 112), 2),
  volume = round(runif(n, 100000, 500000))
)

# 转换为xts对象
stock_xts <- xts(stock_data[, -1], order.by = stock_data$date)

# 1. 计算收益率
stock_xts$returns <- diff(log(stock_xts$close))
print(head(stock_xts))

# 2. 按月统计平均收益率
monthly_returns <- apply.monthly(stock_xts$returns, mean, na.rm = TRUE)
print("月平均收益率:")
print(monthly_returns)

# 3. 计算移动平均线(5日、20日)
stock_xts$ma5 <- rollmean(stock_xts$close, k = 5, fill = NA)
stock_xts$ma20 <- rollmean(stock_xts$close, k = 20, fill = NA)

# 4. 查找金叉信号(5日均线上穿20日均线)
stock_xts$signal <- ifelse(!is.na(stock_xts$ma5) & !is.na(stock_xts$ma20),
                           ifelse(stock_xts$ma5 > stock_xts$ma20 & 
                                  lag(stock_xts$ma5) <= lag(stock_xts$ma20), 1, 0), 0)

# 5. 统计信号数量
signal_count <- sum(stock_xts$signal, na.rm = TRUE)
print(paste("金叉信号出现次数:", signal_count))

# 6. 提取金叉日期的数据
signal_dates <- stock_xts[stock_xts$signal == 1]
print("金叉信号日期的数据:")
print(signal_dates)

案例2:时间区间计算(工作日统计)

r 复制代码
library(lubridate)

# 定义项目起止时间
project_start <- ymd("2026-04-01")
project_end <- ymd("2026-06-30")

# 生成所有日期序列
all_dates <- seq(project_start, project_end, by = "day")

# 提取工作日(周一到周五)
workdays <- all_dates[!wday(all_dates) %in% c(1, 7)]  # 去除周六(7)周日(1)
print(paste("工作日总数:", length(workdays)))
print(paste("休息日总数:", length(all_dates) - length(workdays)))

# 计算每月工作日
workdays_by_month <- table(month(workdays, label = TRUE))
print("每月工作日分布:")
print(workdays_by_month)

# 排除节假日示例
holidays <- ymd(c("2026-05-01", "2026-06-01"))  # 五一、六一劳动节

# 实际工作日(排除节假日)
actual_workdays <- setdiff(workdays, holidays)
print(paste("排除节假日后工作日:", length(actual_workdays)))

# 显示节假日
print("法定节假日:")
print(holidays)

十、要点回顾

知识点 功能 主要函数/包
基本日期函数 获取当前日期时间 Sys.Date(), Sys.time(), date()
时间类转换 转换为POSIX格式 as.POSIXct(), as.POSIXlt()
日期格式转换 字符串与日期互转 as.Date(), format()
日期运算 日期加减、时间差 difftime(), 直接 -
lubridate包 处理日期时间 ymd(), month(), %within%, 时区转换
zoo包 不规则时间序列 zoo(), na.approx(), rollmean()
xts包 高性能时间序列 xts(), apply.monthly(), to.daily()
序列生成 生成规则时间序列 seq(, by="days"), seq(, by="hour")
时间聚合 按周期统计 apply.monthly(), period.apply()
缺失值处理 插值、填充 na.locf(), na.approx()

注意事项

  1. 日期计算要注意时区问题(使用 lubridatewith_tz()
  2. 时间序列降采样时注意选择合适的聚合函数(均值、总和等)
  3. 缺失值处理前应先确认数据结构(regular vs irregular)
  4. ts()xts/zoo 适用场景不同(规则周期 vs 任意时间点)
相关推荐
叼烟扛炮1 小时前
C++ 知识点18 内部类
开发语言·c++·算法·内部类
噜噜噜阿鲁~1 小时前
python学习笔记 | 9.2、模块-安装第三方模块
笔记·python·学习
TAN-90°-2 小时前
Java 3——getter和setter super()关键字
java·开发语言
wand codemonkey2 小时前
(二十七)Maven(依赖)【安装】+【项目结构】
java·开发语言·maven
linda公馆2 小时前
Maven项目报错:java:错误:不支持发行版本 5
java·开发语言·maven
Ulyanov2 小时前
《从质点到位姿:基于Python与PyVista的导弹制导控制全栈仿真》: 可视化革命——基于 PyVista 的 3D 战场构建与实时渲染
开发语言·python·算法·3d·系统仿真
Heaphaestus,RC2 小时前
Slate到UMG的封装原理揭秘
开发语言·ue5
爱喝热水的呀哈喽2 小时前
一段即插即用的hypermesh命令行
开发语言·python
Ulyanov2 小时前
《从质点到位姿:基于Python与PyVista的导弹制导控制全栈仿真》: 终极试炼——全链路综合仿真与蒙特卡洛打靶
开发语言·python·系统仿真·雷达电子对抗