【问题标题】:Rank subgroup by group (dplyr)按组对子组进行排名 (dplyr)
【发布时间】:2021-07-12 17:01:36
【问题描述】:

This question 解决了如何在组中分配行的等级。我想将子组的排名分配给该子组中的一行。我真正想说的是,我需要第二个group_by 变量的缩写,它保证是唯一的,这是我能想到的最好的方法。希望下面的期望输出能够清楚地说明这一点。

输入数据框:

my_df <- tibble(
  var1 = c(rep("A", 8), rep("B", 12)),
  var2 = c(rep("long_string_x", 4), 
           rep("long_string_y", 4),
           rep("long_string_x", 4), 
           rep("long_string_y", 4), 
           rep("long_string_z", 4))
)

期望的输出:

# A tibble: 20 x 3
   var1  var2          group_rank
   <chr> <chr>              <dbl>
 1 A     long_string_x          1
 2 A     long_string_x          1
 3 A     long_string_x          1
 4 A     long_string_x          1
 5 A     long_string_y          2
 6 A     long_string_y          2
 7 A     long_string_y          2
 8 A     long_string_y          2
 9 B     long_string_x          1
10 B     long_string_x          1
11 B     long_string_x          1
12 B     long_string_x          1
13 B     long_string_y          2
14 B     long_string_y          2
15 B     long_string_y          2
16 B     long_string_y          2
17 B     long_string_z          3
18 B     long_string_z          3
19 B     long_string_z          3
20 B     long_string_z          3

我如何分配group_rank 如上所述,理想情况下(但不一定)使用 tidyverse 方法?

【问题讨论】:

  • 您好!只是为了澄清你想要什么:让 G = {var1, var2} 成为所有分组变量的集合,让 S = {var2}是定义您的子组的一组变量;最后令 T = G \ S = {var1} 为 S 中的relative complement i>G。是否要在 T 定义的每个组内为 S 定义的每个子组编制索引?也就是说:您是否要按 T 中的变量进行分组,然后在每个组的上下文中,进一步按 S 对数据进行分组并对这些数据进行“排名”子组?

标签: r dplyr


【解决方案1】:

我们可以在分组后使用match

library(dplyr)
my_df %>% 
   group_by(var1) %>%
   mutate(group_rank = match(var2, unique(var2))) %>%
   ungroup

-输出

# A tibble: 20 x 3
   var1  var2          group_rank
   <chr> <chr>              <int>
 1 A     long_string_x          1
 2 A     long_string_x          1
 3 A     long_string_x          1
 4 A     long_string_x          1
 5 A     long_string_y          2
 6 A     long_string_y          2
 7 A     long_string_y          2
 8 A     long_string_y          2
 9 B     long_string_x          1
10 B     long_string_x          1
11 B     long_string_x          1
12 B     long_string_x          1
13 B     long_string_y          2
14 B     long_string_y          2
15 B     long_string_y          2
16 B     long_string_y          2
17 B     long_string_z          3
18 B     long_string_z          3
19 B     long_string_z          3
20 B     long_string_z          3

【讨论】:

  • 这样就行了!对于我在管道中的位置,我猜想解决方案将在group_by(var1, var2) 之后。该解决方案将起作用;在按var2 分组之前,我只需要在我的管道中比我预期的更早使用它。谢谢。
  • @RobCreel 然后,分组会有所不同,因为它将是 'var1'、'var2' 的唯一值的组合
【解决方案2】:

使用方法来解决受人尊敬的@akrun 的问题

library(tidyverse)
my_df <- tibble(
  var1 = c(rep("A", 8), rep("B", 12)),
  var2 = c(rep("long_string_x", 4), 
           rep("long_string_y", 4),
           rep("long_string_x", 4), 
           rep("long_string_y", 4), 
           rep("long_string_z", 4))
)

my_df %>% 
  group_by(var1) %>% 
  mutate(res = data.table::rleid(var2))
#> # A tibble: 20 x 3
#> # Groups:   var1 [2]
#>    var1  var2            res
#>    <chr> <chr>         <int>
#>  1 A     long_string_x     1
#>  2 A     long_string_x     1
#>  3 A     long_string_x     1
#>  4 A     long_string_x     1
#>  5 A     long_string_y     2
#>  6 A     long_string_y     2
#>  7 A     long_string_y     2
#>  8 A     long_string_y     2
#>  9 B     long_string_x     1
#> 10 B     long_string_x     1
#> 11 B     long_string_x     1
#> 12 B     long_string_x     1
#> 13 B     long_string_y     2
#> 14 B     long_string_y     2
#> 15 B     long_string_y     2
#> 16 B     long_string_y     2
#> 17 B     long_string_z     3
#> 18 B     long_string_z     3
#> 19 B     long_string_z     3
#> 20 B     long_string_z     3

reprex package (v2.0.0) 于 2021-07-12 创建

【讨论】:

  • 很高兴见到您,Saraykin 先生,我永远不会忘记您之前对t.test 问题的慷慨建议。非常感谢。
【解决方案3】:

更新: 正如 Greg 指出的那样(参见 cmets)group_by() 默认为 .add = FALSE,其意图是使用两次 group_by -> 然后应添加 .add = TRUE。 喜欢:

library(dplyr)
my_df %>% 
    group_by(var1) %>% 
    mutate(group_rank = cur_group_id()) %>% 
    group_by(var2, .add=TRUE) %>% 
    mutate(group_rank = cur_group_id())

但在这种情况下,正如 Greg 指出的那样 -> 这已经足够了:

my_df %>% group_by(var2) %>% mutate(group_rank = cur_group_id())

第一个答案: 我们可以使用cur_group_id() 两次:

library(dplyr)
my_df %>% 
    group_by(var1) %>% 
    mutate(group_rank = cur_group_id()) %>% 
    group_by(var2) %>% 
    mutate(group_rank = cur_group_id())

输出:

   var1  var2          group_rank
   <chr> <chr>              <int>
 1 A     long_string_x          1
 2 A     long_string_x          1
 3 A     long_string_x          1
 4 A     long_string_x          1
 5 A     long_string_y          2
 6 A     long_string_y          2
 7 A     long_string_y          2
 8 A     long_string_y          2
 9 B     long_string_x          1
10 B     long_string_x          1
11 B     long_string_x          1
12 B     long_string_x          1
13 B     long_string_y          2
14 B     long_string_y          2
15 B     long_string_y          2
16 B     long_string_y          2
17 B     long_string_z          3
18 B     long_string_z          3
19 B     long_string_z          3
20 B     long_string_z          3

【讨论】:

  • 很好地使用了cur_group_id()我的朋友。
  • 我错过了什么吗?由于group_by() 默认为.add = FALSE,那么group_by(var2) 将覆盖现有的分组(由var1)并简单地留下由var2 分组的my_df单独。然后mutate(group_rank = cur_group_id()) 将简单地覆盖原来的group_rank,而cur_group_id() 用于当前分组:仅由var2。这个结果不是和my_df %&gt;% group_by(var2) %&gt;% mutate(group_rank = cur_group_id())一模一样吗?
  • 谢谢格雷格。这是个好的观点。我不记得为什么我在这里用这种方式。我认为目的是添加.add=TRUE。不知何故,它是这样工作的。无论如何,这个想法是添加第二个group_by。我将编辑我的答案!再次感谢!
猜你喜欢
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多