在不同 类 中随机选择不同大小的组

groups of different size randomly selected within different classes

我有一个如此困难的问题(至少对我而言)以至于我花了 2 个小时才写出来。完全不可能自己编程。我尽量说得很清楚,如果我没有说清楚,我很抱歉。我在 excel 中以一种非常质朴的方式进行此操作,但我确实需要对其进行编程。 我有一个 data.frame 这样的

id_pix id_lote clase   f1   f2
45       4      Sg    2460 2401
46       4      Sg    2620 2422
47       4      Sg    2904 2627
48       5      M     2134 2044
49       5      M     2180 2104
50       5      M     2127 2069
83      11      S     2124 2062
84      11      S     2189 2336
85      11      S     2235 2162
86      11      S     2162 2153
87      11      S     2108 2124

17451 "id_pixel"(行),2080 "id_lote" 和 9 "clase"

这是每个 "clase" 的 "id_lote" 计数(v1 是 id_lote 计数)

 clase   v1
1:     S 1099
2:     P  213
3:    Sg  114
4:     M  302
5:   Alg   27
6:    Az   77
7:    Po  228
8:   Cit   13
9:    Ma    7

我需要在 "clase" 中随机拆分 "id_lote"。我的意思是我有 1099 "id_lote" 用于 "S" "clase" 是 9339 "id_pixel" (行)我想随机 select 50 % of "id_lote" 即 x "id_pixel"(行)。考虑到每个 "clase" 的大小("id_lote" 的数量)不同,对每个 "clase" 执行此操作。我还希望能够更改 selection 的大小(50%、30% 等)。我还想保留未 selected 的 "id_lote" 集。我希望有人能帮我解决这个问题!

这是可重现的例子

这是具有 2 个分类(S 和 Az)的数据,具有 6 个 id_lote 和 13 个 id_pixel

id_pix  id_lote clase   f1  f2
1       1        S    2909  2381
2       1        S    2515  2663
3       1        S    2628  3249
30      2        S    3021  2985
31      2        S    3020  2596
71      9        S    4725  4404
72      9        S    4759  4943
75      11       S    2728  2225
218     21       Az   4830  3007
219     21       Az   4574  2761
220     21       Az   5441  3092
1155    126      Az   7209  2449
1156    126      Az   7035  2932

一个结果可能是:

id_pix  id_lote clase   f1  f2
    1       1        S    2909  2381
    2       1        S    2515  2663
    3       1        S    2628  3249
    75      11       S    2728  2225
    1155    126      Az   7209  2449
    1156    126      Az   7035  2932

id_lote 中有 50% 是随机 select 在 clase "S" 中编辑的(4 个中的 2 个 id_lote),但是 id_pixel 中的所有 id_pixel保留了 70=]ed id_lote。对于 "Az" 类也是如此,一个 id_lote 被随机 selected(在这种情况下是 2 个中的 1 个)并且 select 中的所有 id_pixel 被 id_lote 被保留了。

colemand77 的建议很有帮助。我认为 dplyr 包对此很有用,但我认为如果我这样做

df %>%
group_by(clase, id_lote) %>%
sample_frac(.3, replace = FALSE)

我得到了每个分类的 30% 的数据,但没有像我需要的那样按 id_lote 分组!我的意思是 30% 的行 (id_pixel) 是 select 而不是 id_lote。 我希望这个例子有助于理解我想做什么,并使它对每个人都有用。对不起,如果我第一次不够清楚。 非常感谢!

第一眼我会说 dplyr 包是你的朋友。

df %>%
group_by(clase, id_lote) %>%
sample_frac(.3, replace = FALSE)

所以您首先使用 group_by() 并包括您要从中抽样的分组级别,然后您使用 sample_frac 对每个组的结果分数进行抽样。 据我所知,这就是您所要求的。如果不是,请考虑重新陈述您的问题以包含可重现的示例或进行澄清。干杯。

到 "keep" 未 selected 成员,我会添加一列唯一 ID,并使用反连接 anti_join()(也来自 dplyr 包)到找到两者之间不相同的 ID data.frames(抽样结果和原始结果)。


##更新##

我相信我现在理解得更好了。将此视为一个两步过程...... 1) 你想要 select x% (例如 50) 来自每个 clase 的 id_lote 和 return 那些 id_lote #s (我假设给定的 id_lote 不存在多个类?) 2) 你想看到与每个 id_lote 相对应的所有 id_pixels,所有 data.frame

我将其分解为多个步骤进行说明,并不是因为它是最快/最漂亮的。

原始数据:(无法将您的数据读入 R。)

df<-data.frame(id_pix = c(1:200), 
           id_lote = sample(1:20,200, replace = TRUE),
           clase = sample(letters[seq_along(1:10)], 200, replace = TRUE),
           f1 = sample(1000:2000,200, replace = TRUE),
           f2 = sample(2000:3000,200, replace = TRUE))

1) 找出哪个 id_lote 对应于哪个 clase - 为此我们使用 dplyr summarise 函数并将其存储在变量

summary<-df %>%
  ungroup() %>%
  group_by(clase, id_lote) %>%
  summarise()

returns:

Source: local data frame [125 x 2]
Groups: clase

   clase id_lote
1      a       1
2      a       2
3      a       4
4      a       5
5      a       6
6      a       7
7      a       8
8      a       9
9      a      11
10     a      12
..   ...     ...

然后我们抽样以获得每个类别的 id_lote 的 30%..

sampled_summary <- summary %>%
  group_by(clase) %>%
  sample_frac(.3,replace = FALSE) 

所以这个结果是一个数据 table 有两列(类和 id_lote),每个类显示 30% 的 id_lote。

2) 好的,现在我们从每个 class 中随机 select 编辑了 id_lote,而不是与 class 关联的 id_pix ].为此,我们执行 join 以获得相应的完整数据集,包括 id_pix 等

result <- sampled_summary %>%
  left_join(df)

上面将数据集复制了一堆,所以如果你有大量的数据集,你可以一次性完成:

result <- df %>%
  ungroup() %>%
  group_by(clase, id_lote) %>%
  summarise() %>%
  group_by(clase) %>%
  sample_frac(.5,replace = FALSE) %>%
  left_join(df)

如果这不能满足您的需求,请告诉我,我们会再试一次。