I've got a dataframe that looks similar to this:
Factor1 Factor2 Value
1 A 1 -0.1169027
2 B 1 0.4153005
3 B 2 -1.8824073
4 B 3 0.2627502
5 C 1 0.8822784
6 C 2 0.5011568
7 C 3 0.2332566
8 C 4 0.1897866
9 C 5 -1.4404080
10 C 6 0.3414159
What I'm interested in doing is writing a piece of code that will store in a new dataframe bootstrap samples of each Factor1 level based on the maximum number of distinct samples in Factor2.
library(tidyverse)
sampleGroups <- df %>%
group_by(Factor1) %>%
select(Factor1, Factor2) %>%
summarise(n_distinct(Factor2))
sampleGroups ## max = 6
The samples need to be done with replacement, once all unique levels of Factor2, within each level of Factor1 have been selected.
So a suitable output for the table above would look like this:
Factor1 Factor2 Value
1 A 1 -0.1169027
2 A 1 -0.1169027
3 A 1 -0.1169027
4 A 1 -0.1169027
5 A 1 -0.1169027
6 A 1 -0.1169027
7 B 1 0.4153005
8 B 2 1.8824073
9 B 3 0.2627502
10 B 1 0.4153005
11 B 2 -1.8824073
12 B 2 -1.8824073
13 C 1 0.8822784
14 C 2 0.5011568
15 C 3 0.2332566
16 C 4 0.1897866
17 C 5 -1.4404080
18 C 6 0.3414159
Where you can see that Factor1 = A was repeated 6 times, Factor1 = B was repeated 6 times, but Factor2 within Factor1(B) was bootstrapped with repeats after all levels of Factor2 within Factor1(B) were selected, and then Factor1(C) was selected 6 times as this is where the highest number of unique levels of Factor2 were found.
My real dataset has 20 levels of Factor1, and 17 unique levels of Factor2 nested within Factor1.
Is something like this easy to accomplish in R? Perhaps using dplyr? I've got code that will randomly select a sample from Factor2 for each level of Factor1, but I cannot figure out how to force it to select all levels of Factor2 for each level of Factor1 with replacement (where necessary).
dfBoot <- tibble(Bootstrap = integer(0), Factor1 = character(0), Factor2 = character(0))
for (i in 1:10) {
selected <- df %>%
group_by(Factor1) %>%
select(Factor1, Factor2) %>%
sample_n(1) %>%
mutate(Bootstrap = i)
dfBoot <- bind_rows(dfBoot, selected)
}
dfBoot
# A tibble: 30 x 3
Bootstrap Factor1 Factor2
<int> <chr> <chr>
1 1 A 1
2 1 B 2
3 1 C 1
4 2 A 1
5 2 B 1
6 2 C 5
7 3 A 1
8 3 B 2
9 3 C 3
10 4 A 1
# ... with 20 more rows
And adding in replace = TRUE to the sample_n line above, results in a dataframe with the correct number of sample, but each level of Factor2 is sampled randomly, where I need the replacement to only occur once ALL levels of Factor2 have already been selected.
dfBoot <- tibble(Bootstrap = integer(0), Factor1 = character(0), Factor2 = character(0))
for (i in 1:10) {
selected <- df %>%
group_by(Factor1) %>%
select(Factor1, Factor2) %>%
# sample with replacement this time
sample_n(6, replace = TRUE) %>%
mutate(Bootstrap = i)
dfBoot <- bind_rows(dfBoot, selected)
}
# A tibble: 180 x 3
Bootstrap Factor1 Factor2
<int> <chr> <chr>
1 1 A 1
2 1 A 1
3 1 A 1
4 1 A 1
5 1 A 1
6 1 A 1
7 1 B 1
8 1 B 3
9 1 B 2
10 1 B 2
# ... with 170 more rows
dfBoot
library(tidyverse)- KaanKaant