如何在 r 中为嵌套组创建组索引

  • 本文关键字:嵌套 创建组 索引 r
  • 更新时间 :
  • 英文 :


我有一个数据集,其中嵌套在个人体内的多个观察结果。此示例数据集包括 id 和星期几(日周,1-7(的列。我从每个人那里获得了 3 天的观察结果。因此,一个人可能只提交了周日/周三/周四 (1, 4, 5( 的报告,而另一个人可能提交了周日/周一/周二 (1, 2, 3( 的报告,如以下示例所示:

df <- data.frame(
  id = c(rep(1:2, each = 6),2),
  dayweek = c(rep(c(1, 4, 5), each = 2),rep(c(1, 2, 3), each = 2), 3)
)

我想设置一列来标记每个人的第一天、第二天和第三天,如下所示:

df2 <- data.frame(
  id = c(rep(1:2, each = 6),2),
  dayweek = c(rep(c(1, 4, 5), each = 2),rep(c(1, 2, 3), each = 2), 3),
  daynum = c(rep(1:3, each = 2, times = 2), 3)
)

我试过使用

df %>% group_indices(id, dayweek) 

但这会为每个单独的日期组合生成一个新 ID。有什么好方法可以做到这一点?

提前感谢!

dplyr

cumsum!duplicateddplyr结合使用

df %>%
  group_by(id) %>%
  mutate(daynum = cumsum(!duplicated(dayweek)))

# A tibble: 13 x 3
# Groups:   id [2]
      id dayweek daynum
   <dbl>   <dbl>  <int>
 1     1       1      1
 2     1       1      1
 3     1       4      2
 4     1       4      2
 5     1       5      3
 6     1       5      3
 7     2       1      1
 8     2       1      1
 9     2       2      2
10     2       2      2
11     2       3      3
12     2       3      3
13     2       3      3

从基础R tapply

unlist(tapply(df$dayweek, df$id, function(x) cumsum(!duplicated(x))))
 1  1  2  2  3  3  1  1  2  2  3  3  3 

我们可以为每个dayweek group_by id并创建一个唯一的id

library(dplyr)
df %>%
  group_by(id) %>%
  mutate(daynum = as.integer(factor(dayweek, levels = unique(dayweek))))
#      id dayweek daynum
#   <dbl>   <dbl>  <int>
# 1     1       1      1
# 2     1       1      1
# 3     1       4      2
# 4     1       4      2
# 5     1       5      3
# 6     1       5      3
# 7     2       1      1
# 8     2       1      1
# 9     2       2      2
#10     2       2      2
#11     2       3      3
#12     2       3      3
#13     2       3      3

在基数 R 中,我们可以将 ave 用于相同的

with(df, ave(dayweek, id, FUN = function(x) 
         as.integer(factor(x, levels = unique(x)))))
#[1] 1 1 2 2 3 3 1 1 2 2 3 3 3

根据OP的评论,行是按顺序排列的。

然后,这里有两种不同的方法,也可以处理评论中提到的"星期五,星期六,星期日"的情况(dayweek 6,7,1(。

  1. rleid()
  2. fct_inorder()

rleid()

这使用 data.table 包中的 rleid() 函数:

library(dplyr)
df2 %>% 
  group_by(id) %>% 
  mutate(daynum2 = data.table::rleid(dayweek)) 
      id dayweek daynum daynum2
   <dbl>   <dbl>  <dbl>   <int>
 1     1       1      1       1
 2     1       1      1       1
 3     1       4      2       2
 4     1       4      2       2
 5     1       5      3       3
 6     1       5      3       3
 7     2       1      1       1
 8     2       1      1       1
 9     2       2      2       2
10     2       2      2       2
11     2       3      3       3
12     2       3      3       3
13     2       3      3       3
14     3       6      1       1
15     3       7      2       2
16     3       1      3       3

请注意,使用的扩展数据集也涵盖了"星期五,星期六,星期日"的情况(dayweek 6,7,1(。

fct_inorder()

这是Ronak答案的增强版本,也处理"星期五,星期六,星期日"的情况。它使用 forcats 包中的fct_inorder(),该包按首次出现对因子水平重新排序。

df2 %>% 
  group_by(id) %>% 
  mutate(daynum2 = 
           dayweek %>% 
           as.character() %>% 
           forcats::fct_inorder() %>% 
           as.integer()
         ) 

输出与上述相同。

数据

这是一个扩展数据集,还包括"星期五,星期六,星期日"的情况(dayweek 6,7,1(:

df2 <- data.frame(
  id = c(rep(1:2, each = 6), 2, rep(3, 3)),
  dayweek = c(rep(c(1, 4, 5), each = 2),rep(c(1, 2, 3), each = 2), 3, 6, 7, 1),
  daynum = c(rep(1:3, each = 2, times = 2), 3, 1:3)
)

最新更新