过滤掉 R/Python 中的记录序列
Filter out sequences of records in R/Python
我有一个 table 不同个体的顺序记录,看起来像这样:
(在 R 中设置,尽管 Python 解决方案也可以。)
set.seed(22)
df <- data.frame(
score = c(1, 4, 15, 12, 6, 7, 12, 7, 8, 5, 12, 19, 1, 4, 7, 12, 3, 5, 9, 4),
info = sample(1:100, 20)
)
score
info
1
9
4
88
15
74
12
94
6
44
7
59
12
81
7
67
8
48
5
16
12
58
19
72
1
62
4
31
7
65
12
49
3
21
5
68
9
33
4
32
目标是根据分数序列过滤掉 table 的某些行。这是人类逻辑中的规则。以分数为榜单:
1, 4, 15, 12, 6, 7, 12, 7, 8, 5 12, 19, 1, 4, 7 12, 3, 5, 9, 4
第 1 步:根据分数 == 12 的实例将列表分成子列表。
(无论最后一个子列表是否以 score == 12 结尾,它都会被包括在内。如果列表不包含任何 score == 12 的实例,则将有一个子列表,即:整个列表。)
[1, 4, 15, 12], [6, 7, 12], [7, 8, 5, 12], [19, 1, 4, 7, 12], [3, 5, 9, 4]
第 2 步:过滤掉所有不包含一个或多个 scores == 4 实例的子列表。
[1, 4, 15, 12], [19, 1, 4, 7, 12], [3, 5, 9, 4]
第 3 步:然后过滤数据框以仅包含与这些分数对应的行。
score
info
1
9
4
88
15
74
12
94
19
72
1
62
4
31
7
65
12
49
3
21
5
68
9
33
4
32
请注意,分数既不唯一也不是有序的。
在 R 或 Python 中实现此例程的最佳方法是什么,最好不要使用循环?
使用base R
,我们可以在逻辑向量(score == 12
)上使用cumsum
来创建分组列,然后filter
如果有4 %in%
分数只保留那些组,最后删除创建的 grp
列 - dplyr
用于管道,lag
library(dplyr)
df %>%
group_by(grp = lag(cumsum(score == 12), default = 0)) %>%
filter(4 %in% score) %>%
ungroup %>%
select(-grp)
-输出
# A tibble: 13 × 2
score info
<dbl> <int>
1 1 9
2 4 88
3 15 74
4 12 94
5 19 72
6 1 62
7 4 31
8 7 65
9 12 49
10 3 21
11 5 68
12 9 33
13 4 32
这是一个基本的 R 方法。
- 首先创建一个
vec
向量,其中包含索引位置df$score == 12
。还包括 0 和 now(df)
到它,稍后将在 lapply
中使用
- 创建以
score == 12
结尾的子列表 mylist
。 deframe
用于使用 lapply
从 two-column 数据帧创建命名向量
- 使用
%in%
运算符查看子列表中是否包含4,去掉不包含4的子列表
- 并使用
enframe
从命名向量创建 two-column 数据框。
vec <- sort(c(0, which(df$score == 12), nrow(df)))
mylist <- lapply(1:(length(vec) - 1), function(x) deframe(df[2:1])[(vec[x]+1):vec[x+1]])
enframe(mylist[sapply(mylist, function(x) 4 %in% x)] %>% unlist(), value = "score", name = "info")[2:1]
# A tibble: 13 × 2
score info
<int> <chr>
1 1 9
2 4 88
3 15 74
4 12 94
5 19 72
6 1 62
7 4 31
8 7 65
9 12 49
10 3 21
11 5 68
12 9 33
13 4 32
我有一个 table 不同个体的顺序记录,看起来像这样:
(在 R 中设置,尽管 Python 解决方案也可以。)
set.seed(22)
df <- data.frame(
score = c(1, 4, 15, 12, 6, 7, 12, 7, 8, 5, 12, 19, 1, 4, 7, 12, 3, 5, 9, 4),
info = sample(1:100, 20)
)
score | info |
---|---|
1 | 9 |
4 | 88 |
15 | 74 |
12 | 94 |
6 | 44 |
7 | 59 |
12 | 81 |
7 | 67 |
8 | 48 |
5 | 16 |
12 | 58 |
19 | 72 |
1 | 62 |
4 | 31 |
7 | 65 |
12 | 49 |
3 | 21 |
5 | 68 |
9 | 33 |
4 | 32 |
目标是根据分数序列过滤掉 table 的某些行。这是人类逻辑中的规则。以分数为榜单:
1, 4, 15, 12, 6, 7, 12, 7, 8, 5 12, 19, 1, 4, 7 12, 3, 5, 9, 4
第 1 步:根据分数 == 12 的实例将列表分成子列表。
(无论最后一个子列表是否以 score == 12 结尾,它都会被包括在内。如果列表不包含任何 score == 12 的实例,则将有一个子列表,即:整个列表。)
[1, 4, 15, 12], [6, 7, 12], [7, 8, 5, 12], [19, 1, 4, 7, 12], [3, 5, 9, 4]
第 2 步:过滤掉所有不包含一个或多个 scores == 4 实例的子列表。
[1, 4, 15, 12], [19, 1, 4, 7, 12], [3, 5, 9, 4]
第 3 步:然后过滤数据框以仅包含与这些分数对应的行。
score | info |
---|---|
1 | 9 |
4 | 88 |
15 | 74 |
12 | 94 |
19 | 72 |
1 | 62 |
4 | 31 |
7 | 65 |
12 | 49 |
3 | 21 |
5 | 68 |
9 | 33 |
4 | 32 |
请注意,分数既不唯一也不是有序的。
在 R 或 Python 中实现此例程的最佳方法是什么,最好不要使用循环?
使用base R
,我们可以在逻辑向量(score == 12
)上使用cumsum
来创建分组列,然后filter
如果有4 %in%
分数只保留那些组,最后删除创建的 grp
列 - dplyr
用于管道,lag
library(dplyr)
df %>%
group_by(grp = lag(cumsum(score == 12), default = 0)) %>%
filter(4 %in% score) %>%
ungroup %>%
select(-grp)
-输出
# A tibble: 13 × 2
score info
<dbl> <int>
1 1 9
2 4 88
3 15 74
4 12 94
5 19 72
6 1 62
7 4 31
8 7 65
9 12 49
10 3 21
11 5 68
12 9 33
13 4 32
这是一个基本的 R 方法。
- 首先创建一个
vec
向量,其中包含索引位置df$score == 12
。还包括 0 和now(df)
到它,稍后将在lapply
中使用
- 创建以
score == 12
结尾的子列表mylist
。deframe
用于使用lapply
从 two-column 数据帧创建命名向量
- 使用
%in%
运算符查看子列表中是否包含4,去掉不包含4的子列表 - 并使用
enframe
从命名向量创建 two-column 数据框。
vec <- sort(c(0, which(df$score == 12), nrow(df)))
mylist <- lapply(1:(length(vec) - 1), function(x) deframe(df[2:1])[(vec[x]+1):vec[x+1]])
enframe(mylist[sapply(mylist, function(x) 4 %in% x)] %>% unlist(), value = "score", name = "info")[2:1]
# A tibble: 13 × 2
score info
<int> <chr>
1 1 9
2 4 88
3 15 74
4 12 94
5 19 72
6 1 62
7 4 31
8 7 65
9 12 49
10 3 21
11 5 68
12 9 33
13 4 32