You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中基于多列添加可按时间排序的递增索引

问题描述

我有一个包含hour(小时)、day(星期)、month(月份)和count(计数)列的数据框:

library(tidyverse)

set.seed(0)

df <- expand_grid(expand_grid(
  hour = seq(0:23),
  day = c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")),
  month = c("Jan", "Feb", "Mar", "Apr", "May", "Jun")) %>%
  mutate(count = sample(0:100, n(), replace = TRUE))

head(df)

输出结果:

# A tibble: 6 × 4
   hour day   month count
  <int> <chr> <chr> <int>
1     1 Mon   Jan      13
2     1 Mon   Feb      67
3     1 Mon   Mar      38
4     1 Mon   Apr       0
5     1 Mon   May      33
6     1 Mon   Jun      86

我想添加一个名为id的递增索引列,用来标记数据的时间顺序。目前的方法需要先设置因子水平再调用arrange(),不够简洁。有没有办法利用日期特性来解决这个问题?

我当前的解决方案:

df2 <- df %>%
  mutate(day = factor(day, levels = c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")),
         month = factor(month, levels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun"))) %>%
  arrange(month, day, hour) %>%
  mutate(id = row_number())

head(df2)

输出结果:

# A tibble: 6 × 5
   hour day   month count    id
  <int> <fct> <fct> <int> <int>
1     1 Mon   Jan      13     1
2     2 Mon   Jan      43     2
3     3 Mon   Jan      82     3
4     4 Mon   Jan      66     4
5     5 Mon   Jan      49     5
6     6 Mon   Jan      79     6

解决方案:利用日期特性自动排序

这里提供两种无需手动设置因子水平的方法,都能借助日期相关工具实现自动排序:

方法1:构造完整日期时间对象排序

借助lubridate包的日期解析功能,将现有字段组合成可排序的日期时间对象,再生成索引:

library(tidyverse)
library(lubridate)

df3 <- df %>%
  # 构造虚拟日期字符串(用固定年份补全年份缺失)
  mutate(date_str = str_c("2024-", month, "-", day, " ", hour, ":00"),
         # 自动解析成日期时间对象,lubridate能识别英文月份/星期缩写
         datetime = parse_date_time(date_str, "%Y-%b-%a %H:%M")) %>%
  # 按日期时间排序
  arrange(datetime) %>%
  # 生成递增id
  mutate(id = row_number()) %>%
  # 可选:移除辅助列
  select(-date_str, -datetime)

head(df3)

输出结果:

# A tibble: 6 × 5
   hour day   month count    id
  <int> <chr> <chr> <int> <int>
1     0 Mon   Jan      27     1
2     1 Mon   Jan      13     2
3     2 Mon   Jan      43     3
4     3 Mon   Jan      82     4
5     4 Mon   Jan      66     5
6     5 Mon   Jan      49     6

方法2:提取日期数值排序

如果不想构造完整日期,也可以直接提取月份、星期的对应数值来排序,更轻量:

df4 <- df %>%
  mutate(
    # 把月份缩写转成1-12的数字
    month_num = match(month, month.abb),
    # 把星期缩写转成1-7的数字(周一为1)
    day_num = match(day, c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))
  ) %>%
  arrange(month_num, day_num, hour) %>%
  mutate(id = row_number()) %>%
  # 移除辅助列
  select(-month_num, -day_num)

head(df4)

这个方法的输出结果和方法1完全一致,且无需额外加载lubridate包。


内容的提问来源于stack exchange,提问作者FST

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:16:04