我有一个数据集,其中嵌套在个人体内的多个观察结果。此示例数据集包括 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
和!duplicated
与dplyr
结合使用
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(。
-
rleid()
-
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)
)