Генерация псевдослучайной двоичной последовательности с условиями в R

Я хочу сгенерировать 5 блоков псевдослучайных двоичных последовательностей (для хранения в фрейме данных) со следующими условиями для каждого блока:

  1. 150 0 с

  2. 25 1с

  3. Последовательность не может начинаться или заканчиваться цифрой 1.

  4. 1 должны быть разделены минимум одним 0 и максимум 12 0.

Это моя текущая (неудачная) попытка. Проблема здесь в том, что в нескольких случаях я получаю более 12 последовательных нулей, и это обычно происходит в конце блока. Меня не слишком беспокоит распределение, а только количество нулей, разделяющих единицы.

library(plyr)
library(EnvStats)
#> 
#> Attaching package: 'EnvStats'
#> The following objects are masked from 'package:stats':
#> 
#>     predict, predict.lm

# variables
lure <- 1
target <- 0
nBlock <- 5
ntrialBlock <- 175
nTrial <- nBlock * ntrialBlock
nLureTrials <- 125
nTargets <- nTrial - nLureTrials
distMean <- 6.23
distSD <- 2.55
distLower <- 1
distUpper <- 12

# create trials and block numbers
block <- rep(1:nBlock, each=ntrialBlock) 
trial <- 1:nTrial

# store in data frame for trial matrix
trialMatrix <- data.frame(block, trial)

# pseudorandomisation
nLureTrialsBlock <- nLureTrials/nBlock

lureMatrix <- ddply(trialMatrix, .(block), function(trialMatrix) {
  
  lureMatrix <- data.frame()
  blockSum <- 0
  blockSet <- data.frame(x = numeric())
  blockTotal <- 0
  blockAg <- blockSum + (ntrialBlock*(trialMatrix[1,1]-1))
  
  while ((nrow(blockSet) != nLureTrialsBlock) & (blockSum < (ntrialBlock-distUpper))) {
    
    rand_draw <- round(rnorm(1, mean = distMean, sd = distSD))
    # Append to array
    blockSet[nrow(blockSet) + 1,] <- rand_draw
    # Get number of congruent trials in this block
    blockSum <- sum(blockSet)
    # Get trial numbers which are congruent trials
    # Take cumulative sum (keep adding prev trial)
    blockTotal <- cumsum(blockSet)
    blockAg <- blockSum + (ntrialBlock*(trialMatrix[1,1]-1)) 
    
  }
  
  blockSet <- cumsum(blockSet) + (ntrialBlock*(trialMatrix[1,1]-1))
  lureMatrix <- rbind(lureMatrix, blockSet) 
  
  return(lureMatrix)
  
}) 

# store lures in trialMatrix
trialMatrix[lureMatrix$x, "lure"] <- 1
trialMatrix[is.na(trialMatrix)] <- 0

Created on 2024-06-19 with репрекс v2.1.0

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
69
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете попробовать подход «грубой силы», который не займет много времени, чтобы добиться успеха. Функцию rle можно использовать для определения длины последовательных значений.

data <- data.frame(block=rep(1:5, each=175), trial=seq(1, 175*5)) 

f <- function(n0, n1) {
  x <- c(0, 
         sample(c(rep(0,148), rep(1,25)), size=173, replace=FALSE), 
         0) # initial guess

  while(any(rle(x)$lengths[which(rle(x)$values==0)] > n0) ||
        any(rle(x)$lengths[which(rle(x)$values==1)] > n1)) {

    x <- c(0, 
           sample(c(rep(0,148), rep(1,25)), size=173, replace=FALSE), 
           0)
  }
  x
}

data <- dplyr::mutate(data, lure=f(n0=12, n1=1), .by=block)

Поскольку вы не указываете, сколько может быть ведущих или конечных нулей (их может быть больше 12), вы можете рассматривать проблему как случайную последовательность из 24 групп единиц, за которыми следуют от 1 до 12 нулей, затем единица, затем случайная ведущие и конечные нули до заполнения 75

Для одного столбца:

  1. Создайте последовательность из 24 чисел от 2 до 13, сумма которых должна быть < 175 - 3 (два нуля плюс дополнительная 1). Это будут последовательности единиц, за которыми следуют нули.
  2. Разверните последовательность с помощью повтора и транспонированной матрицы и добавьте единицу.
  3. Добавить случайные ведущие нули
  4. Полностью отсутствующие конечные нули
while (sum(x <- sample(2:13, 24, T)) > 175 - 3) {}
middle <- c(rep(rep(c(1,0), 24),t(cbind(1, x - 1))), 1)
leading <- rep(0,  sample(175 - length(middle), 1))
trailing <- rep(0, 175 - length(middle) - length(leading))

c(leading, middle, trailing)

Вывод для столбца:

00100000001001000000010000100000000
10000000000100001000000100000100100
00001010001000100001000000000100100
00000000100000100001000010000000000
01000001000000000100000000000000000

затем цикл для каждого столбца.

ПД: я использовал set.seed(23921) в начале программы

Вероятно, вы можете использовать rmultinom, чтобы сделать это

n0s <- 150
n1s <- 25
max0len <- 12
repeat {
  d <- rmultinom(1, n0s - 2 - (n1s + 1), rep(1, n1s + 1)) + 1 # distribution of `0`s (separated by `1`s, where total number of `0` is `n0s - 2` (excluding head and tail of the sequence), while guaranteeing one `0` at least
  if (max(d) <= max0len) break # the max run length of `0`s shouldn't be greater than `12`
}
s <- rep(rep(c(0, 1), length.out = 2 * n1s + 1), c(d[1], rbind(1, d[-1])))

и вы можете получить такую ​​последовательность s например

> s
  [1] 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0
 [38] 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
 [75] 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
[112] 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
[149] 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0

А как насчет других критериев, согласно которым «1 должны быть разделены как минимум одним 0»?

Edward 19.06.2024 14:25

@Эдвард, ага, спасибо за напоминание, я упустил из виду это условие. Смотрите мое обновление

ThomasIsCoding 19.06.2024 22:45

Другие вопросы по теме