提问人:mto23 提问时间:8/17/2023 最后编辑:mto23 更新时间:8/17/2023 访问量:59
选择每组连续 1 的行
Select rows per group with consecutive 1s
问:
我有一个数据帧,我想通过仅选择连续值“1”来对其进行子集。
具体来说,我有一个数据帧,如下所示:
library(tidyverse)
library(zoo)
df <- data.frame(matrix(ncol = 3, nrow = 17))
colnames(df) <- c("row_id","id", "k_yes")
df$row_id <- c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)
df$id <- c("1_1","1_1","1_1","1_1","1_1","1_1","1_2","1_2","1_2","1_2","1_2","1_2","1_3","1_3","1_3","1_3","1_3")
df$k_yes <- c(1,1,1,0,1,1,0,0,0,1,1,0,1,0,1,0,1)
df
row_id id k_yes
1 1 1_1 1
2 2 1_1 1
3 3 1_1 1
4 4 1_1 0
5 5 1_1 1
6 6 1_1 1
7 7 1_2 0
8 8 1_2 0
9 9 1_2 0
10 10 1_2 1
11 11 1_2 1
12 12 1_2 0
13 13 1_3 1
14 14 1_3 0
15 15 1_3 1
16 16 1_3 0
17 17 1_3 1
我想创建两个数据集:
1) 一个,每个组 () 只有“1”,但总是两个或两个以上连续。因此,如果两个“1”之间有一个“0”,至少应该丢弃最后一个“1”。因此,它将接受诸如 、 、 依此类推,但不是 或id
1-1
1-1-1
0-1-1
1-1-1-0
然后,我还希望添加一列以了解已形成的新组/序列,因为它并不总是与 id 相同(如果 id 中有两个子组/序列)。基本上,对于整个数据帧,此列的每个序列都应该有一个唯一的代码(现在,我只是用一个字母绑定了 id,但它可以是一个连续的数字/字母,例如)
此数据帧如下所示:
row_id id k_yes new_group
1 1 1_1 1 1_1_A
2 2 1_1 1 1_1_A
3 3 1_1 1 1_1_A
4 5 1_1 1 1_1_B
5 6 1_1 1 1_1_B
6 10 1_2 1 1_2_A
7 11 1_2 1 1_2_A
2) 另一个,每组 () 接受“1”之间的一个“0”,但如果“0”之后没有其他“1”,则不接受。
因此,它将接受诸如 、 、 、 等的序列,但不接受 or or 之类的序列(在后者中,它只会保留前 1 个)。“new_group”列与之前相同。id
1-0-1
1-1-0-1
1-1-0-1-1
1-1-0-1-0-1
0-1-1
1-1-0
1-1-0-0-1
df 的预期输出为:
row_id id k_yes new_group
1 1 1_1 1 1_1_A
2 2 1_1 1 1_1_A
3 3 1_1 1 1_1_A
4 4 1_1 0 1_1_A
5 5 1_1 1 1_1_A
6 6 1_1 1 1_1_A
7 10 1_2 1 1_2_A
8 11 1_2 1 1_2_A
9 12 1_3 1 1_3_A
10 14 1_3 0 1_3_A
11 15 1_3 1 1_3_A
12 16 1_3 0 1_3_A
13 17 1_3 1 1_3_A
在本例中,id “1_1” 仅获取“新组”(1_1_A) 的一个值,因为它都是相同的序列(包括 0)
我尝试遵循这个答案,但没有成功,因为我尝试过:
> df |>
group_by(id) |>
mutate(b = c(first(k_yes) , zoo::rollsum(k_yes, 1))) |>
summarise(groups_to_keep = id[which(b >= 2)]) -> gk
Error in `mutate()`:
ℹ In argument: `b = c(first(k_yes), zoo::rollsum(k_yes, 1))`.
ℹ In group 1: `id = "1_1"`.
Caused by error:
! `b` must be size 5 or 1, not 6.
我认为问题出在功能上,但是在检查了帮助页面后,我仍然不清楚应该如何应用此功能。rollsum()
任何帮助都是值得赞赏的!
更新:
我添加了一个新版本的数据集,它将在第一个数据集 (1) 中为“新组”创建两个值。
答:
1赞
Mark
8/17/2023
#1
对于数据集 #1:
df |>
filter(k_yes & (lag(k_yes) | lead(k_yes)), .by = id) |>
mutate(new_group = row_number() == 1 | row_id - 1 != lag(row_id), .by = id) |>
mutate(new_group = paste0(id, "_", LETTERS[cumsum(new_group)]), .by = id)
数据集 2:
df |>
filter(k_yes | (!k_yes & lag(k_yes) & lead(k_yes)), .by = id) |>
mutate(new_group = row_number() == 1 | row_id - 1 != lag(row_id), .by = id) |>
mutate(new_group = paste0(id, "_", LETTERS[cumsum(new_group)]), .by = id)
评论
0赞
mto23
8/17/2023
多谢!这有帮助,但仅适用于数据集 1 - 对数据集 2 有什么想法吗?我也忘记了我想添加一个新列来标识新组(请参阅问题中的编辑),关于如何将其包含在您提供的代码中的任何想法?
1赞
Mark
8/17/2023
@mto23更新:-)
1赞
Mark
8/17/2023
两个问题:1.您说的是数据集 1 还是 2?2.输出应该是什么?(添加问题,请不要在评论中! :-)
1赞
mto23
8/17/2023
我的错!我现在用新的示例和输出编辑了这个问题。关于第一个问题,在我提供的示例中,它只会影响数据集 1,但它也适用于数据集 2。谢谢!!
1赞
mto23
8/17/2023
现在工作得很好,非常感谢!!:)
评论