Home > Net >  Random Sample From a Dataframe With Specific Count
Random Sample From a Dataframe With Specific Count

Time:03-31

This question is probably best illustrated with an example.

Suppose I have a dataframe df with a binary variable b (values of b are 0 or 1). How can I take a random sample of size 10 from this dataframe so that I have 2 instances where b=0 in the random sample, and 8 instances where b=1 in the dataframe?

Right now, I know that I can do df[sample(nrow(df),10,] to get part of the answer, but that would give me a random amount of 0 and 1 instances. How can I specify a specific amount of 0 and 1 instances while still taking a random sample?

CodePudding user response:

Here's an example of how I'd do this... take two samples and combine them. I've written a simple function so you can "just take one sample."

With a vector:

pop <- sample(c(0,1), 100, replace = TRUE)

yoursample <- function(pop, n_zero, n_one){
  c(sample(pop[pop == 0], n_zero),
    sample(pop[pop == 1], n_one))
}

yoursample(pop, n_zero = 2, n_one = 8)
[1] 0 0 1 1 1 1 1 1 1 1

Or, if you are working with a dataframe with some unique index called id:

# Where d1 is your data you are summarizing with mean and sd
dat <- data.frame(
    id = 1:100,
    val = sample(c(0,1), 100, replace = TRUE),
    d1 = runif(100))

yoursample <- function(dat, n_zero, n_one){
  c(sample(dat[dat$val == 0,"id"], n_zero),
    sample(dat[dat$val == 1,"id"], n_one))
}

sample_ids <- yoursample(dat, n_zero = 2, n_one = 8)  
sample_ids

mean(dat[dat$id %in% sample_ids,"d1"])
sd(dat[dat$id %in% sample_ids,"d1"])

CodePudding user response:

Here is a suggestion:

First create a sample of 0 and 1 with id column. Then sample 2:8 df's with condition and bind them together:

library(tidyverse)

set.seed(123)
df <- as_tibble(sample(0:1,size=50,replace=TRUE)) %>% 
  mutate(id = row_number())

df1 <- df[ sample(which (df$value ==0) ,2), ]
df2 <- df[ sample(which (df$value ==1), 8), ]    

df_final <- bind_rows(df1, df2)
   value    id
   <int> <int>
 1     0    14
 2     0    36
 3     1    21
 4     1    24
 5     1     2
 6     1    50
 7     1    49
 8     1    41
 9     1    28
10     1    33

CodePudding user response:

library(tidyverse)

set.seed(123)

df <- data.frame(a = letters,
                 b = sample(c(0,1),26,T))

bind_rows(
  df %>% 
    filter(b == 0) %>% 
    sample_n(2),
  df %>% 
    filter(b == 1) %>% 
    sample_n(8)
) %>% 
  arrange(a)

   a b
1  d 1
2  g 1
3  h 1
4  l 1
5  m 1
6  o 1
7  p 0
8  q 1
9  s 0
10 v 1
  • Related