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 任意时间点)
相关推荐
我命由我1234542 分钟前
复利极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
从零开始的代码生活_1 小时前
C++ 内存管理:从内存分区到 new/delete 底层原理
开发语言·c++·后端
wabs6661 小时前
关于单调栈【力扣739.每日温度的思考】
java·开发语言
AOwhisky1 小时前
Python 学习笔记(第三期)——流程控制核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发·流程控制
tyqtyq221 小时前
药品说明书解读 —— AI 安全用药助手,鸿蒙原生应用深度解析
人工智能·学习·华为·生活·harmonyos
小心亦新2 小时前
STM32学习13 定时器1中断
stm32·嵌入式硬件·学习
逆向编程2 小时前
Socket异常连接自动清理方案
开发语言
我命由我123453 小时前
72 法则极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
qq_263_tohua3 小时前
第112期 CNN学习,不错的文章
学习
va学弟3 小时前
Java 网络通信编程(10):Channel 和 Selector
java·开发语言