0
votes

Here is my data:

df <- tibble::tribble(
  ~group, ~sort_var, ~var, ~desired_rank,
      1L,        3L,  "A",            1L,
      1L,        4L,  "A",            1L,
      1L,        5L,  "D",            2L,
      1L,        6L,  "C",            3L,
      2L,        1L,  "D",            1L,
      2L,        2L,  "B",            2L,
      2L,        3L,  "C",            3L,
      2L,        4L,  "B",            2L)

The data is already arranged using sort_var by group. I want to rank the contents of the var as they come within the group. For example, D comes 2nd within group 1 so it gets rank 2, while it get's rank 1 in group 2 as it comes 1st in that group.

I tried this, but getting an incorrect output.

df %>% group_by(group) %>% 
  mutate(incorrect_rank = rank(var))

Please suggest a solution.

2

2 Answers

2
votes

A semi-tidyverse option using match

library(dplyr)
df %>% group_by(group) %>% 
  mutate("(in)correct_rank" = match(var, unique(var)))
# A tibble: 8 x 5
# Groups:   group [2]
#  group sort_var var   desired_rank `(in)correct_rank`
#  <int>    <int> <chr>        <int>              <int>
#1     1        3 A                1                  1
#2     1        4 A                1                  1
#3     1        5 D                2                  2
#4     1        6 C                3                  3
#5     2        1 D                1                  1
#6     2        2 B                2                  2
#7     2        3 C                3                  3
#8     2        4 B                2                  2
1
votes

A dplyr and data.table solution:

df %>%
    group_by(group)  %>%
    mutate(temp = rleid(var)) %>%
    group_by(group, var) %>%
    mutate(rank = ifelse(temp != 0, first(temp), NA)) %>%
    ungroup() %>%
    select(-temp)

  group sort_var var   desired_rank  rank
  <int>    <int> <chr>        <int> <int>
1     1        3 A                1     1
2     1        4 A                1     1
3     1        5 D                2     2
4     1        6 C                3     3
5     2        1 D                1     1
6     2        2 B                2     2
7     2        3 C                3     3
8     2        4 B                2     2