【问题标题】:Rank function in R after group by分组后R中的排名函数
【发布时间】:2020-09-29 05:35:44
【问题描述】:

如何使用 R 创建排名列?下面是一个例子
这就是我所拥有的:


Date       group
12/5/2020    A
12/5/2020    A
11/7/2020    A
11/7/2020    A
11/9/2020    B
11/9/2020    B
10/8/2020    B

这就是我想要的:

Date       group   rank
12/5/2020    A      2
12/5/2020    A      2
11/7/2020    A      1
11/7/2020    A      1
11/9/2020    B      2
11/9/2020    B      2
10/8/2020    B      1

【问题讨论】:

  • 嗨雨莎。欢迎来到堆栈溢出。你能告诉我们为什么排名是这样的吗?从您的示例中不是很清楚。

标签: r dataframe rank


【解决方案1】:

Date列转换为实际的日期对象,arrangeDate的数据,并使用matchunique得到rank列。

library(dplyr)

df %>%
  mutate(Date = lubridate::mdy(Date)) %>%
  arrange(group, Date) %>%
  group_by(group) %>%
  mutate(rank = match(Date, unique(Date)))

#  Date       group  rank
#  <date>     <chr> <int>
#1 2020-11-07 A         1
#2 2020-11-07 A         1
#3 2020-12-05 A         2
#4 2020-12-05 A         2
#5 2020-10-08 B         1
#6 2020-11-09 B         2
#7 2020-11-09 B         2

数据

df <- structure(list(Date = c("12/5/2020", "12/5/2020", "11/7/2020", 
"11/7/2020", "11/9/2020", "11/9/2020", "10/8/2020"), group = c("A", 
"A", "A", "A", "B", "B", "B")), class = "data.frame", row.names = c(NA, -7L))

【讨论】:

    【解决方案2】:

    tidyverse

    (我在这里使用dplyr,因为我认为很容易看到正在执行的步骤。)

    第一种方法可能是利用 R 的 factor 函数,该函数为每个不同的值分配一个整数,以便对这个 factor 的操作更快(与字符串相比)。也就是说,它需要一个(可能很长)字符串向量并将其转换为一个长度相同的整数向量(更小更快)和一个非常短的字符串向量,其中整数是小向量的索引字符串。这个小向量称为因子的“水平”。

    library(dplyr)
    group_by(dat, group) %>%
      mutate(rank = as.integer(factor(Date))) %>%
      ungroup()
    # # A tibble: 7 x 3
    #   Date      group  rank
    #   <chr>     <chr> <int>
    # 1 12/5/2020 A         2
    # 2 12/5/2020 A         2
    # 3 11/7/2020 A         1
    # 4 11/7/2020 A         1
    # 5 11/9/2020 B         2
    # 6 11/9/2020 B         2
    # 7 10/8/2020 B         1
    

    这种“排序”有效,但有两个问题:

    1. 这取决于Date 列的字典排序,对此数据样本是可接受的,但这会失败。更好的方法是转换为更适合排序的对象,例如 Date 对象。

      排序失败:

      sort(c("12/9/2020", "11/9/2020", "2/9/2020"))
      # [1] "11/9/2020" "12/9/2020" "2/9/2020" 
      
    dat %>%
      mutate(Date = as.Date(Date, format = "%m/%d/%Y")) %>%
      group_by(group) %>%
      mutate(rank = as.integer(factor(Date))) %>%
      ungroup()
    # # A tibble: 7 x 3
    #   Date       group  rank
    #   <date>     <chr> <int>
    # 1 2020-12-05 A         2
    # 2 2020-12-05 A         2
    # 3 2020-11-07 A         1
    # 4 2020-11-07 A         1
    # 5 2020-11-09 B         2
    # 6 2020-11-09 B         2
    # 7 2020-10-08 B         1
    

    1. 确实有更好的排名函数,例如dplyr::dense_rank(@akrun 首先给出了答案......老实说,我正在构建它):
    dat %>%
      mutate(Date = as.Date(Date, format = "%m/%d/%Y")) %>%
      group_by(group) %>%
      mutate(rank = dense_rank(Date)) %>%
      ungroup()
    # # A tibble: 7 x 3
    #   Date       group  rank
    #   <date>     <chr> <int>
    # 1 2020-12-05 A         2
    # 2 2020-12-05 A         2
    # 3 2020-11-07 A         1
    # 4 2020-11-07 A         1
    # 5 2020-11-09 B         2
    # 6 2020-11-09 B         2
    # 7 2020-10-08 B         1
    

    【讨论】:

    • 我的失败是没有写出最终答案first。 *耸耸肩*
    【解决方案3】:

    我们可以在将“日期”转换为Date类后使用dense_rank

    library(dplyr)
    library(lubridate)
    df1 %>% 
          group_by(group) %>% 
          mutate(rank = dense_rank(mdy(Date)))
    # A tibble: 7 x 3
    # Groups:   group [2]
    #  Date      group  rank
    #  <chr>     <chr> <int>
    #1 12/5/2020 A         2
    #2 12/5/2020 A         2
    #3 11/7/2020 A         1
    #4 11/7/2020 A         1
    #5 11/9/2020 B         2
    #6 11/9/2020 B         2
    #7 10/8/2020 B         1
    

    数据

    df1 <- structure(list(Date = c("12/5/2020", "12/5/2020", "11/7/2020", 
    "11/7/2020", "11/9/2020", "11/9/2020", "10/8/2020"), group = c("A", 
    "A", "A", "A", "B", "B", "B")), class = "data.frame", row.names = c(NA, 
    -7L))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-03
      • 2021-11-01
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多