Выборка случайных строк, равномерно распределенных по R

Имею df измерений за 50 лет. Я пытаюсь сделать подвыборку данных, чтобы увидеть, какие закономерности я бы нашел, если бы выбрал только 2 года или 3, 4, 5 и т. Д. Вместо всех 50. Я сделал код, который будет извлекать случайные годы из набор данных, но с условием, что эти два случайных года, по крайней мере, распределены в наборе данных (с разницей в 10 лет или что-то в этом роде).

Есть ли какой-нибудь код условной случайной выборки?

Вот чем я пока занимаюсь. Было бы проще остаться в этом формате, потому что отсюда я %>% перейду к другим вещам.

# build df
df = data.frame(year=c(1:50),
                response = runif(50,1,100))

# set number of times I'll do the simulation
number_simulations <- 5 

# set number of years I'll sample in each simulation
# (I later put this in a for loop so that I could repeat 
#  this process with more and more sample years)
number_samples <- 2



df %>% 
  
  # repeat df x number of times
  replicate(number_simulations, ., simplify = FALSE) %>%  
  
  # pick n random samples from df
  map_dfr(~ sample_n(., number_samples), .id = "simulation")

# Can I change this code to make sure sampled years aren't too close to each other? 
# years 23 and 25 out of 50 won't tell me much. But 23 and 35 would be fine. 

Я думаю, что проще всего было бы создать функцию для sample_n_conditional(), чтобы я мог просто заменить sample_n в строке map_dfr. Это должна быть функция, которая говорит о какой-то выборке в n лет с разницей не менее 10 лет. Или даже что-то более динамичное, зависящее от количества образцов, поскольку 10-летний интервал станет неустойчивым, когда я буду тянуть больше лет. Это больше похоже на выборку n лет, которые разумно пропорционально распределены по рядам.

Я подумал о том, чтобы изменить общее количество симуляций на большее, чем мне нужно, а затем отфильтровать те, которые находятся слишком близко друг к другу, предполагая, что достаточно случайности будет соответствовать моей квалификации. Но это не идеально.

Любые идеи приветствуются.


person Jake L    schedule 06.07.2020    source источник


Ответы (1)


Вы можете использовать цикл repeat, который прерывается, только если threshold превышает определенное значение.

n.sim <- 5  ## number of simulations
n.samp <- 2  ## number of samples (also works for n.samp > 2)
thres <- 10  ## threshold

set.seed(42)
res <- replicate(n.sim, {
  repeat({
    samp <- df[sample(1:nrow(df), n.samp), ]
    if (all(abs(diff(samp[["year"]])) > thres)) break
    })
  samp
}, simplify=F)

Результат

res
# [[1]]
# year  response
# 49   49 97.125694
# 37   37  1.726081
# 
# [[2]]
# year  response
# 1     1 91.565798
# 25   25  9.161318
# 
# [[3]]
# year response
# 10   10 70.80141
# 36   36 83.45869
# 
# [[4]]
# year response
# 18   18 12.63125
# 49   49 97.12569
# 
# [[5]]
# year response
# 47   47 88.88774
# 24   24 94.72016

Данные:

set.seed(42)
df <- data.frame(year=1:50, response=runif(50, 1, 100))
person jay.sf    schedule 06.07.2020