1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
Решение SPSS AnswerNet 

Код решения:	 	100000483	
Продукт:	 	SPSS Base 	
Версия:	 		
ОС:	 		
Тип вопроса:	 	Синтаксис/Скрипты/Пакетный режим	
Подтип вопроса:	 	Дата и время	
Заголовок:
Генерация случайных дат из заданного интервала 
Описание:
Вопрос. Как мне сгенерировать 100 случайных дат между 1 января
1920 года и 31 декабря 1989, включительно? 

Ответ. Ниже представлены 2 варианта синтаксиса. Первый осуществляет
случайную выборку дат с возвращением, т.е. некоторая дата может
быть отобрана более одного раза. Второй вариант делает выборку без возвращения.
После этих двух примеров приводятся несколько команд, с помощью которых
вы можете получить представление о распределении дат, полученных в 
результате.

Вариант 1: даты отбираются с возвращением:
Даты хранятся в SPSS как число секунд, прошедших с начала отсчёта
григорианского календаря, т.е. с полуночи 14 октября 1582 года. Для
создания каждой случайной даты программа генерирует случайное число секунд
из интервала, соответствующего нужному интервалу дат, и сохраняет его в
переменной RDAY. Функция XDATE.DATE "отсекает" часть дня таким образом, что
переменная RDAY содержит число секунд, прошедших до полуночи (до начала) данного дня.
После этого с помощью формата даты настраивается нужное отображение содержимого
RDAY (в данном случае используем формат ADATE10). Обратите внимание, в качестве конечной
даты интервала был выбран следующий день после 31.12.1989. Это потому, что 
функция генерации случайных чисел rv.uniform(a,b) генерирует числа между a и b, не
включая края интервала. Таким образом, указав конечную дату 01.01.1990, мы гарантируем, что 
максимальным числом, сгенерированным функцией rv.uniform, будет число, 
соответствующее 11:59:59 31 декабря 1989 года. Для начальной даты указывать 
предыдущий день не требуется. Хотя число, в точности соответствующее полуночи 1 января
1920 года не может быть сгенерировано, любое число, начиная со следующей за
полуночью секундой и до последней секунды этого дня, будет отнесено к 1 января 1920 году.

*генерируем 100 случайных дат между 1.1.1920 и 31.12.1989 (включительно).
*с возвращением.
new file. 
input program. 
loop #i = 1 to 100. 
compute rday = xdate.date(rv.uniform(date.dmy(1,1,1920),date.dmy(1,1,1990))). 
end case. 
end loop. 
end file. 
end input program. 
execute. 
formats rday (adate10). 

Вариант 2. даты отбираются без возвращения: 
Для выбора без возвращения мы сначала составляем полный список дат
из заданного интервала так, чтобы каждая дата повторялась в нём лишь один
раз. В переменную RDAY мы помещаем числа, начиная с числа дней, прошедших с 
начала отсчёта григорианского календаря к 1.1.1920, и заканчиваем числом дней, 
прошедших с той же точки отсчёта к 31.12.1989. Каждое новое наблюдение,
таким образом, представляет собой очередную дату. Использование функции
YRMODA освобождает нас от необходимости высчитывать начало и конец цикла LOOP вручную.
Затем мы генерируем случайную переменную и добавляем её к файлу данных. После этого 
мы ранжируем наблюдения по значениям этой случайной переменной. Ранги сохраняются
в переменной RX. Значения рангов - не что иное, как случайный порядок дней в нужном нам
интервале. Отбирая наблюдения, ранги которых RX<=100, мы получаем выборку 100 случайных дней
без возвращения из нужного интервала. Теперь нужно умножить значения RDAY на 86400
(число секунд в сутках) и применить форматирование для переменной даты. 

В отличие от первого варианта, масштаб случайной переменной, генерируемой с помощью
rv.uniform во втором варианте, не важен. Первая и последняя дата временного интервала 
были включены в исходный файл данных. Здесь не нужно указывать верхнюю границу как 1 января 1990
года, чтобы на самом деле получить 31 декабря 1989-го.
* генерируем 100 случайных дат между 1.1.1920 и 31.12.1989 (включительно).
* без возвращения. 
new file. 
input program. 
loop rday = yrmoda(1920,1,1) to yrmoda(1989,12,31). 
compute x = rv.uniform(0,1). 
end case. 
end loop. 
end file. 
end input program. 
execute. 
rank variables = x /rank into rx. 
select if (rx <= 100). 
execute. 
compute rday = rday*86400 . 
formats rday (adate10). 
execute. 

* после получения файла переменные x и rx можно удалить. 
* Для обоих вариантов визуально проверить результаты генерации можно,
* построив распределения полученных дат.
* (для этого предварительно объединим их в декады). 
compute decade = trunc(xdate.year(rday)/10)*10. 
formats decade (f8). 
frequencies decade.

Создано: 25.8.1999.