Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Статистика в SPSS: за пределами кнопочного интерфейса. Выпуск 4


Информационный Канал Subscribe.Ru

Статистика в SPSS: за пределами кнопочного интерфейса. Выпуск 4

В рассылке используются материалы веб-сайта www.spsstools.ru

Содержание выпуска

Разбор синтаксиса, генерирующего триады дискретных случайных величин
Новое на сайте www.spsstools.ru

 

Здравствуйте, уважаемые подписчики,

Разбор синтаксиса, генерирующего триады дискретных случайных величин

Изберём сегодня объектом нашего внимания небольшой синтаксис, размещённый по адресу http://www.spsstools.ru/Syntax/Bootstrap/GenerateRandomTriadNumbers.txt, задачей которого является получение триад дискретных случайных величин. Вот как звучит перевод исходного вопроса, послужившего причиной создания этого синтаксиса:

"Мне нужно симулировать случайные переменные, представляющие собой триады чисел: var1a, var1b, var1c, var2a, var2b, var2c и т.д. Каждая переменная может принимать случайное целое число 0, 1 или 2, но каждая переменная из триады (например, var2a, var2b, var2c), должна иметь РАЗНЫЕ значения. Таким образом, первая из трёх переменных может принимать любое из трёх значений 0, 1 или 2 (я использовал инструкцию COMPUTE var1a = TRUNC(RV.UNIFORM(0,3)) .). Вторая переменная может принимать любое значение из трёх, за исключением того значения, что приняла первая переменная. Третья переменная вычисляется как 3 минус сумма значений двух предыдущих переменных. Моя трудность в том, как получить вторую переменную (и, возможно, элегантное решение как сделать всё это вместе через цикл LOOP, или как-то иначе)".

Действительно, первая переменная может быть сгенерирована каким угодно случайным образом, в том числе и с помощью метода, предложенного автором вопроса (где функция TRUNC возвращает целую часть от значения случайной величины, равномерно распределённой на участке (0, 3). Третья переменная не имеет "степеней свободы", однозначно определяясь значениями двух других. Поэтому "загвоздка" остаётся в генерации значения второй переменной при условии, что значение первой уже сгенерировано.

Впрочем, задача не слишком сложна и решить её можно различными способами.

Ответ был размещён Рейналем Левек в списке рассылки SPSSX-L 1 августа 2002 года. Вот как выглядит этот синтаксис:

*--------------------------------------------------.

INPUT PROGRAM.

LOOP id=1 TO 10.

LOOP varn=1 TO 4.

LEAVE id,varn.

LOOP ctr=1 TO 3.

END CASE.

END LOOP.

END LOOP.

END LOOP.

END FILE.

END INPUT PROGRAM.

LIST.

 

COMPUTE draw=UNIFORM(1).

RANK VARIABLES=draw BY id varn /RANK INTO rk.

VECTOR var(12).

COMPUTE var((varn-1)*3+ctr)=rk.

AGGREGATE
/OUTFILE=*
/BREAK=id
/var1 TO var12 = MAX(var1 TO var12).

 

RENAME VARIABLES (var1 TO var3 = var1a var1b var1c)
/(var4 TO var6 = var2a var2b var2c)
/(var7 TO var9 = var3a var3b var3c)
/(var10 TO var12 = var4a var4b var4c).

*--------------------------------------------------------------.

 

Ключевая идея решения состоит в том, что мы ранжируем значения переменных из одной триады в порядке возрастания случайной величины равномерной плотности на участке (0, 1), которая генерируется независимо для каждой триады. Понятно, что, поскольку генерация идёт с большим числом знаков после запятой, повторение рангов в одной триаде маловероятно и это практически даёт нам заведомо разные дискретные случайные значения. Затем нам остаётся лишь преобразовать данные к тому виду, который требовался в вопросе.

Рассмотрим подробнее как воплотилась данная концепция в синтаксисе. Первые несколько строк генерируют вспомогательные данные, "канву" для нашей работы:

INPUT PROGRAM.

LOOP id=1 TO 10.

LOOP varn=1 TO 4.

LEAVE id,varn.

LOOP ctr=1 TO 3.

END CASE.

END LOOP.

END LOOP.

END LOOP.

END FILE.

END INPUT PROGRAM.

LIST.

 

В ответе предполагается, что нам необходимо сгенерировать 10 наблюдений 4-х триад дискретных случайных переменных. С помощью конструкции INPUT PROGRAM мы заполняем редактор данных нужными переменными. Каждое наблюдение будет содержать:

1. Номер случайного наблюдения (от 1 до 10), которое мы получим в будущем: LOOP id=1 to 10.

2. Номер триады (от 1 до 4): LOOP varn=1 TO 4.

3. Номер переменной в триаде (от 1 до 3, разумеется): LOOP ctr=1 TO 3.

Каждое наблюдение из будущего файла представлено здесь 12 наблюдениями (4 триадами). Чтобы в данных не образовывались пропуски, вызванные генерацией с помощью вложенных циклов LOOP, используется команда LEAVE, указывающая программе, что, заканчивая ввод очередного наблюдения, нужно сохранить значения переменных, полученных и на верхних циклах LOOP, а не только на последнем. Данную команду можно было вставить и после третьего цикла в данном случае. Оканчивает генерацию наблюдения команда END CASE, а файла в целом - END FILE. Команда LIST выполняет преобразования (непосредственно генерацию и заполнение редактора данных) и выводит содержимое файла в окно результатов.

 

На следующем этапе мы выполняем содержательную часть работы. Во-первых, появляется вспомогательная случайная переменная. Её значения распределены равномерно на участке (0, 1).

COMPUTE draw=UNIFORM(1).

Используемое далее ранжирование производится с применением ключевого слова BY, после которого указывается, что ранжирование должно вестись в пределах наблюдений, имеющих одинаковые значения переменных id и varn. Именно эти переменные определяют уникальные триады. Ранги сохраняются в переменную rk.

RANK VARIABLES=draw BY id varn /RANK INTO rk.

Собственно, эти ранги уже представляют собой дискретные случайные значения (понятно, что наблюдение из триады могло равновероятно оказаться первым, вторым или третьим в каждом случае). Теперь надо перевести полученный результат к виду, который запрашивал автор, а именно - получить триады переменных. Иными словами, сейчас у нас триады записаны в один столбец, в наблюдения. Нам надо повернуть их так, чтобы триады стали переменными и при этом сохранить 10 наблюдений каждой триады.

 

Для этого мы определим вектор из 12 переменных (так как у нас должно быть 4 триады), которые по умолчанию будут иметь числовой формат F8.2.

VECTOR var(12).

Команда создаёт переменные вектор переменных var1, var2, ..., var12, которые допускают индексную адресацию в виде var(индекс). Индексная адресация, помимо преимущества компактности кода при оперировании многими однотипными переменными, позволит нам в следующей команде произвести условные вычисления:

COMPUTE var((varn-1)*3+ctr)=rk.

Инструкция, приведённая выше, присваивает переменной, имеющей индекс (varn-1)*3+ctr, ранг, полученный ранее. Таким образом, соответствующие значения из переменной rk будут приписаны не всем значениям переменной var1, например, а только тем наблюдениям, для которых индекс (varn-1)*3+ctr действительно будет равен единице. Легко увидеть, что это будут ранги для первой переменной первой триады. Таких рангов будет 10, поскольку мы генерируем 10 наблюдений. Выполните синтаксис в пошаговом режиме до этой инструкции, и вы увидите, что столбцы переменных v1-v12 заполнены как бы в шахматном порядке, с большим количеством пропусков. Теперь мы "сожмём" таблицу по горизонтали, удалив эти пропуски и получив из 120 имеющихся строк 10 наблюдений. Рейналь Левек осуществил эту операцию с помощью команды AGGREGATE, которая как раз предназначена для проведения "обобщающих" преобразований данных.

AGGREGATE
/OUTFILE=*
/BREAK=id
/var1 TO var12 = MAX(var1 TO var12).

Инструкция OUTFILE=* указывает, что результат работы AGGREGATE будет помещён в редактор данных (текущий файл), а не во внешний файл (такая возможность действительно существует, если вместо звёздочки указать путь и имя файла).

Инструкция BREAK определяет подгруппы наблюдений, для которых будут производиться преобразования. В частности, команда AGGREGATE будет выделять наблюдения с одинаковыми значениями переменной id (т.е. каждый раз будет брать по 12 строк) и выполнять некоторые преобразования.

Характер преобразований задаётся в следующей инструкции после "слэша". Запись "/var1 TO var12 = MAX(var1 TO var12)" эквивалентна записи "/var1 = MAX(var1) /var2= MAX(var2) ...и т.д. /var12 = MAX(var12)". То есть несколько последовательных инструкций заменяются одной с использованием ключевого слова TO. Такая последовательная адресация переменных возможна в некоторых командах в SPSS. Суть преобразований такова, что для поднабора из 12 строк с одинаковыми значениями переменной id в новом файле будет создана 1 строка (одно наблюдение), где каждая из 12 переменных var1-var12 получает максимальное значение из всех 12 значений соответствующей переменной в исходном файле данных. Напомним, что, поскольку ранее мы заполнили столбцы var1-var12 в шахматном порядке, набор из 12 строк содержит лишь одно значение для каждой переменной. В этом случае нам, вообще говоря, всё равно, какую функцию взять для обобщения: MAX, MIN, MEAN (т.е. среднее значение)...

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

RENAME VARIABLES (var1 TO var3 = var1a var1b var1c)
/(var4 TO var6 = var2a var2b var2c)
/(var7 TO var9 = var3a var3b var3c)
/(var10 TO var12 = var4a var4b var4c).

Теперь практически всё сделано. Наблюдательный критик заметит, что автору нужны были комбинации чисел 0, 1, 2, а не 1, 2, 3, которые мы сгенерировали из-за того, что использовали ранжирование. Чтобы быть совсем точными в ответе, можно вставить перед командой RENAME VARIABLES следующие инструкции:

VECTOR var = var1 to var12.

LOOP #i=1 to 12.

COMPUTE var(#i) = var(#i)-1.

END LOOP.

EXECUTE.

Команду VECTOR мы используем здесь в ином виде, не в таком как раньше, поскольку здесь мы не создаём новые переменные, а ссылаемся на уже существующие. Суть предлагаемых преобразований проста - мы просто уменьшаем каждое значение каждой переменной на единицу, приводя данные к тому виду, который был нужен автору вопроса. Поскольку, скорее всего, значения 1, 2, 3, будут означать коды, не принципиальна замена их именно числами 0, 1, 2. Поэтому Рейналь не предлагал в своём решении указанных нами преобразований, оставив нам приятную возможность для такого усовершенствования. :)

Всего вам доброго!

 

Ведущий рассылки,

Балабанов Антон

Новое на сайте www.spsstools.ru

Переведены и добавлены следующие примеры синтаксиса:

 

Все сочетания по 3 числа из 9.SPS

Найти все сочетания от 1 до n объектов из m объектов.SPS

Найти все сочетания по n объектов из m объектов.SPS

 

© См. www.spsstools.ru, 2005-2006


Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.others.spss
Архив рассылки
Отписаться Вебом Почтой
Вспомнить пароль

В избранное