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

时间:2019-04-21 03:45:02

标签: r

我有一个包含多个嵌套在个体内的观察值的数据集。此示例数据集包括ID和星期几(dayweek,1-7)的列。我从每个人的3天中得到的观察结果。因此,一个人可能只提交了有关Sun / Wed / Thu(1、4、5)的报告,而另一个人可能只提交了针对Sun / Mon / Tue(1、2、3、3)的报告,例如以下示例:

django rest frame work

我想设置一列来标记每个人的第一天,第二天和第三天,就像这样:

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)
)

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

谢谢!

3 个答案:

答案 0 :(得分:4)

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

tapply来自基础R

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

 1  1  2  2  3  3  1  1  2  2  3  3  3 

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

根据OP's comment,这些行是按顺序排列的。

然后,这是两种不同的方法,它们也将处理注释中提到的“星期五,星期六,星期日”情况(dayweek 6、7、1)。

  1. rleid()
  2. fct_inorder()

rleid()

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

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's answer的增强版本,它也处理“星期五,星期六,星期日”情况。它使用fct_inorder()包中的forcats,按首次出现的顺序对因子级别进行重新排序。

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)
)