Добавить случайное значение к случайному блоку в векторе - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть числовой вектор

vect <- c(0,16,11,132,0,0,0,18,28,245,0,0,55,45,19,30,20,0,0,0,12,0)

Существует четыре ряда значений, не равных нулю.

(16,11,132), (18,28,245), (55,45,19,30,20), (12)

Для 1/4 серии (одна серия), выбранной случайным образом, я хочу добавить случайное целочисленное значение в диапазоне от -10 до 10.

Например, если выбранная серия являетсявторое и выбранное значение равно -5, результат будет

vect2 <- c(0,16,11,132,0,0,0,13,23,240,0,0,55,45,19,30,20,0,0,0,12,0)

Это пример только одной строки, функция будет применена ко всей матрице

Ответы [ 3 ]

0 голосов
/ 27 декабря 2018

Вот один длинный лайнер:

vect + with(rle(vect != 0), rep(replace(0 * values, which(values)[sample(sum(values), 1)], sample(-10:10, 1)), lengths))
# [1]   0  16  11 132   0   0   0  18  28 245   0   0  55  45  19  30  20   0   0   0   8   0

Более подробно это будет

tmp <- rle(vect != 0)
add <- sample(-10:10, 1)
tmp$values <- replace(0 * tmp$val, which(tmp$val)[sample(sum(tmp$val), 1)], add)
vect + inverse.rle(tmp)

Итак, мы создаем новый вектор, добавляя второй компонентдо начального vect.Деталь

replace(0 * tmp$val, which(tmp$val)[sample(sum(tmp$val), 1)], add)
# [1] 0 3 0 0 0 0 0 0 0

выбирает один из ненулевых блоков и помещает туда новое случайное значение add.Тогда

inverse.rle(tmp)
# [1] 0 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 голосов
/ 27 декабря 2018

Решение, которое не использует rle.Здесь я использую diff, чтобы найти позиции, которые не 0.Затем случайным образом выберите одну позицию и сгенерируйте вектор нулей, кроме этой одной позиции.

# Extract positions that are not 0
sequences <- c(0, diff(vect != 0))

# Get starts
starts <- which(sequences == 1)
# One random position from starts
position <- sample(seq_along(starts), 1)

# Get absolute start and end positions
currentStart <- starts[position]
currentEnd <- which(sequences == -1)[position] - 1

# Add this vector to originak
addVector <- rep(0, length(vect))
addVector[currentStart:currentEnd] <- rep(sample(-10:10, 1), currentEnd - currentStart + 1)

vect + addVector
0 голосов
/ 27 декабря 2018

Следующий не очень элегантный код, должен работать.Он использует rle.

set.seed(1)
vect <- c(0,16,11,132,0,0,0,18,28,245,0,0,55,45,19,30,20,0,0,0,12,0)

# Get non-zero runs
runs <- rle(vect!=0)
non_zero_runs <- with(runs, lengths[values])

# Sample the required
rand_run <- sample(seq_along(non_zero_runs), size = 1)
print(rand_run)
#[1] 2
rand_int <- sample(-10:10, size = 1)
print(rand_int)
#[1] -3

# Identify the sampled run
which_run <- min(which(cumsum(runs$values) == rand_run))

# Identify the corresponding indices
start <- sum(runs$lengths[seq_len(which_run - 1)]) + 1
end <- start + runs$lengths[which_run] - 1

vect[start:end] <- vect[start:end] + rand_int
print(vect)
#[1]   0  16  11 132   0   0   0  15  25 242   0   0  55  45  19  30  20   0   0   0  12   0

Вы можете попробовать уменьшить код самостоятельно.Кодекс очень многословен, так как он был частью решения и понимания проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...