Menu

Случайные числа в R: rnorm, runif, sample и set.seed

Генерируйте случайные данные через rnorm(), runif(), rbinom() и sample(), делайте их воспроизводимыми через set.seed() и расшифруйте систему имён d/p/q/r для распределений.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

set.seed() идёт первым

Случайные выборки, меняющиеся при каждом запуске, бесполезны для обучения, проверки, отладки и науки: если ваша симуляция говорит 0.146 сегодня и 0.153 завтра, какое число пойдёт в отчёт? set.seed() фиксирует начальную точку генератора, делая весь последующий поток «случайности» в точности повторяемым:

Одно зерно — одинаковые выборки, каждый раз, на любой машине. Числа являются псевдослучайными: детерминированная последовательность, сконструированная так, чтобы проходить любые статистические тесты на случайность, а зерно выбирает, где в этой последовательности вы стартуете. Само значение зерна не несёт смысла — 42, 7, 20260807, — берите что угодно, только запишите. Привычка, которую стоит выработать: один set.seed() в начале любого скрипта, использующего случайность. (Учтите, что потребление выборок продвигает состояние, поэтому для воспроизводимости важен и порядок вызовов.)

Система d/p/q/r: одна таблица расшифровывает всю библиотеку

R именует каждую функцию распределения как префикс + семейство, и, увидев эту сетку, вы сможете читать всю статистическую библиотеку:

ПрефиксНа какой вопрос отвечаетПример для нормального
rДай мне случайные значенияrnorm(5)
dПлотность: какова высота кривой в точке x?dnorm(0)
pВероятность: P(X ≤ x)?pnorm(1.96)
qКвантиль: какой x стоит на этом процентиле?qnorm(0.975)

p и q являются обратными друг другу, и это та пара, с которой вы встретились в доверительных интервалах в виде qt(0.975, df):

Замените имя семейства — и всё переносится: runif/dunif/punif/qunif, rbinom/..., rpois/..., rt/..., rexp/.... Выучите четыре префикса — получите десятки распределений.

rnorm(): нормальные выборки

rnorm(n, mean, sd) берёт значения из колоколообразной кривой — рабочая лошадка для моделирования данных, похожих на измерения:

Выборочные среднее и sd оказываются рядом с 100 и 15, но не точно на них: этот зазор и есть выборочный шум, сокращающийся с ростом n. Последняя строка — приём, который стоит украсть: mean() от логического вектора равно доле значений TRUE, и доля выше 130 выходит близкой к теоретической 1 - pnorm(130, 100, 15) ≈ 2.3%. Умолчания — mean = 0, sd = 1 (стандартное нормальное). Гистограмма по iq покажет знакомый колокол.

runif(), rbinom(), rpois()

Ещё три семейства закрывают большинство потребностей симуляции:

runif() распределяет значения равномерно по диапазону («uniform», а не «run if» — все хоть раз прочитывают неверно). rbinom(n, size, prob) моделирует n экспериментов по size испытаний каждый и возвращает количество успехов в каждом, так что каждое значение выше — это число орлов из 10 бросков. rpois(n, lambda) генерирует количества событий, происходящих независимо с известной средней интенсивностью: заявки в поддержку за час, опечатки на страницу.

sample(): отбор и перемешивание

Там, где функции r* выдумывают значения из распределения, sample() берёт из значений, которые у вас уже есть:

Аргумент replace объясняет всё: FALSE (по умолчанию) раздаёт карты — каждое значение может выпасть один раз, и просьба взять больше, чем есть, является ошибкой; TRUE бросает кости — каждое извлечение начинается заново. Отбор с возвращением из собственных данных — двигатель бутстрепа. Вызванная только с вектором, sample(x) возвращает случайную перестановку — идиома перемешивания.

Отбор строк датафрейма использует sample() внутри индексации строк:

sample(nrow(mtcars), 5) выбирает 5 случайных номеров строк; индексация вытягивает эти строки. Это стандартный приём для выборочной проверки большого набора данных или разделения на обучающую и тестовую выборки.

Мини-симуляция Монте-Карло

Вот ради чего собирался весь инструментарий. Вопрос: процесс даёт измерения, распределённые как N(100, 15); вы усредняете 10 из них — какова вероятность, что это среднее превысит 105? Вместо вывода формулы смоделируйте: проведите эксперимент 10 000 раз и посчитайте:

Симуляция укладывается в пару тысячных от точного значения (около 0.146). Вот Монте-Карло на одном дыхании: опишите одно испытание функцией, повторите её тысячи раз через replicate() и возьмите mean() от успехов. Точный ответ здесь существовал, потому что постановка была учебно простой, — а в момент, когда вопрос становится грязным (странные распределения, максимум коррелированных величин, игра по правилам), аналитический путь закрывается, а рецепт симуляции продолжает работать без изменений. Обратите внимание на 15 / sqrt(10) в проверке: средние колеблются меньше отдельных наблюдений — тот же закон квадратного корня, что задаёт ширину доверительных интервалов.

Годится для симуляции, не годится для секретов

Одна граница, которую нужно уважать: генератор R по умолчанию (Mersenne Twister) создан для статистического качества и скорости, а не для секретности. Его вывод детерминирован при заданном зерне, а внутреннее состояние может быть восстановлено по наблюдаемому выводу — фатальные изъяны для паролей, токенов и всего, что связано с безопасностью. Для симуляции, бутстрепа и обучения он превосходен; для криптографии используйте специализированную библиотеку (например, пакет openssl), но никогда не sample() и не runif().

Что вы уносите с собой

  • Один set.seed() в начале делает каждый «случайный» результат воспроизводимым: одно зерно — одинаковые выборки.
  • Префиксы d/p/q/r расшифровывают всю библиотеку распределений: случайное значение, плотность, накопленная вероятность, квантиль.
  • rnorm(n, mean, sd), runif(n, min, max), rbinom(n, size, prob), rpois(n, lambda) закрывают большинство потребностей симуляции.
  • sample() берёт из ваших собственных значений — replace = TRUE для костей, умолчание для карт, без size для перемешивания; df[sample(nrow(df), k), ] отбирает строки.
  • Монте-Карло = функция одного испытания + replicate() + mean() — рецепт, отвечающий на вероятностные вопросы, до которых математике добраться неудобно.
  • Генератор случайных чисел R предназначен для симуляции, а не для криптографии.

Дальше: отладка — что на самом деле означают сообщения об ошибках R и как читать трассировку вызовов.

Часто задаваемые вопросы

Что делает set.seed() в R?

Она фиксирует начальную точку генератора случайных чисел R, поэтому следующие за ней «случайные» выборки получаются одинаковыми при каждом запуске. Вызовите её один раз в начале любого скрипта, использующего случайность, — set.seed(42), — и ваша симуляция станет воспроизводимой: коллеги, проверяющие и вы в будущем увидите те же числа.

Как сгенерировать случайные числа в R?

Выберите распределение: rnorm(n, mean, sd) для нормальных выборок, runif(n, min, max) для равномерных, rbinom(n, size, prob) для количеств успехов, rpois(n, lambda) для количеств событий. Для отбора из уже существующих значений используйте sample(x, size).

В чём разница между rnorm, dnorm, pnorm и qnorm?

Одно распределение, четыре префикса: r берёт случайные значения, d даёт высоту кривой плотности, p даёт накопленную вероятность P(X ≤ x), а q является обратной к ней — значением на заданном процентиле. Те же четыре префикса работают для любого известного R распределения: runif/dunif/punif/qunif, rbinom/dbinom/pbinom/qbinom и так далее.

Как взять случайную выборку строк из датафрейма в R?

Проиндексируйте строки через sample(): df[sample(nrow(df), 5), ] выбирает 5 строк без возвращения. Добавьте replace = TRUE для отбора с возвращением (приём, лежащий в основе бутстрепа).

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ