R语言:如何从随机选取的id组中提取指定有序行?
问题背景
以示例数据dat0为例,需求是随机提取3组id对(每组id对应2行有序数据):
初始数据(5组id对)
dat0 <- structure(list(id = c("A", "A", "B", "B", "C", "C", "D", "D", "E", "E"), order = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), result = c(94, 95, 28, 22, 54, 52, 12, 13, 58, 57)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame")) dat0 #> id order result #> <chr> <int> <dbl> #> 1 A 1 94 #> 2 A 2 95 #> 3 B 1 28 #> 4 B 2 22 #> 5 C 1 54 #> 6 C 2 52 #> 7 D 1 12 #> 8 D 2 13 #> 9 E 1 58 #> 10 E 2 57
期望输出(3组随机id对)
dat1 #> id order result #> <chr> <int> <dbl> #> 1 B 1 28 #> 2 B 2 22 #> 3 C 1 54 #> 4 C 2 52 #> 5 E 1 58 #> 6 E 2 57
尝试的错误代码
首次使用slice_sample()时,尝试以下分组提取代码,但未得到预期结果(仍保留5组id,且order及对应result混乱):
library(dplyr) dat1 <- dat0 |> group_by(id) |> slice_sample(n = 3) |> ungroup()
需求是找到更简便的实现方式,支持指定选取id组数量(如nid=3)和每组保留的有序行数(如krow=2)。
扩展问题
针对更通用场景,以新数据dat2为例,需从随机选取的3组id中提取每组前3行有序数据(order=1、2、3),同时排除行数不足3行的id(如B和H):
新数据(9组id重复数据)
dat2 <- structure(list(id = c("A", "A", "A", "A", "A", "B", "B", "C", "C", "C", "C", "D", "D", "D", "E", "E", "E", "E", "E", "F", "F", "F", "G", "G", "G", "G", "H", "I", "I", "I", "I", "I"), order = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 1L, 2L, 3L, 4L, 1L, 1L, 2L, 3L, 4L, 5L), result = c(94, 95, 97, 93, 91, 28, 22, 54, 52, 53, 54, 12, 13, 15, 58, 57, 59, 58, 60, 72, 70, 71, 48, 46, 45, 47, 6, 80, 82, 81, 88, 86)), row.names = c(NA, -32L), class = c("tbl_df", "tbl", "data.frame")) print(dat2, n=Inf) #> # A tibble: 32 × 3 #> id order result #> <chr> <int> <dbl> #> 1 A 1 94 #> 2 A 2 95 #> 3 A 3 97 #> 4 A 4 93 #> 5 A 5 91 #> 6 B 1 28 #> 7 B 2 22 #> 8 C 1 54 #> 9 C 2 52 #> 10 C 3 53 #> 11 C 4 54 #> 12 D 1 12 #> 13 D 2 13 #> 14 D 3 15 #> 15 E 1 58 #> 16 E 2 57 #> 17 E 3 59 #> 18 E 4 58 #> 19 E 5 60 #> 20 F 1 72 #> 21 F 2 70 #> 22 F 3 71 #> 23 G 1 48 #> 24 G 2 46 #> 25 G 3 45 #> 26 G 4 47 #> 27 H 1 6 #> 28 I 1 80 #> 29 I 2 82 #> 30 I 3 81 #> 31 I 4 88 #> 32 I 5 86
新期望输出(3组随机id的3行有序数据)
#> id order result #> <chr> <int> <dbl> #> 1 A 1 94 #> 2 A 2 95 #> 3 A 3 97 #> 4 D 1 12 #> 5 D 2 13 #> 6 D 3 15 #> 7 G 1 48 #> 8 G 2 46 #> 9 G 3 45
现寻求该通用场景的简便实现方法。
解决方案
针对问题背景的实现
核心思路是先随机筛选指定数量的id组,再提取每组的前krow行有序数据:
library(dplyr) nid <- 3 krow <- 2 dat1 <- dat0 |> filter(id %in% sample(unique(id), nid)) |> group_by(id) |> slice_head(n = krow) |> ungroup() dat1
针对扩展问题的实现
先过滤出满足行数要求的id,再随机选取指定数量,最后提取每组前指定行数:
library(dplyr) nid <- 3 krow <- 3 # 先筛选出至少有krow行的id valid_ids <- dat2 |> group_by(id) |> filter(n() >= krow) |> pull(id) |> unique() # 提取目标数据 dat3 <- dat2 |> filter(id %in% sample(valid_ids, nid)) |> group_by(id) |> slice_head(n = krow) |> ungroup() dat3
内容的提问来源于stack exchange,提问作者denis
相关产品推荐
相关产品推荐

