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

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


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

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

Макрос попарного разбора признаков

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


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

С мая 2006 года сервис Subscribe.Ru предоставляет получателям HTML-версий рассылок возможность голосования за очередной выпуск (через сайт, либо письмом). В нижнем и верхнем колонтитулах каждого выпуска вы найдёте шкалу для голосования по 5-балльной шкале (где 5 означает наивысший балл). Я просил бы вас по возможности выражать своё мнение относительно содержания, оформления, стиля, полезности полученного вами выпуска в виде этой комплексной оценки. Развёрнутые комментарии вы всегда можете направить мне на a-balabanov( at) yandex.ru.

 

Макрос попарного разбора признаков

Так получилось, что в ходе разработки очередного синтаксиса для SPSS в нём наметилась определённая часть кода, весьма ценная сама по себе. Я выделил её в отдельный макрос и собираюсь сегодня о нём рассказать.

Предположим, требуется построить парные таблицы сопряжённости для всевозможных пар из списка 20 переменных. Всевозможных пар найдётся C220, т.е. 20! / 2!(20-2)! = 190 штук. Соответственно, будет построено такое же количество таблиц (кто уж их будет анализировать в таком количестве - другой вопрос ;-)). Часто к таким сочетаниям приходится прибегать в имитационных исследованиях, когда пытаемся установить эффективность работы того или иного метода с разными параметрами, при поиске оптимальных сочетаний признаков и т.д. Задачам комбинаторики, к слову, посвящён целый раздел в коллекции Рейналя. Так или иначе, появляется потребность в автоматизации подобной работы.

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

 

Идея решения (запускающий макрос). Создадим два цикла. Второй вложен в первый. Оба цикла перебирают один и тот же заданный набор переменных. Во внутреннем цикле происходит проверка на то, что индекс текущей переменной больше индекса текущей переменной из внешнего макроса. Если это условие выполнено, запускаем требуемый макрос, передавая ему в качестве одного из параметров имена двух переменных: одну - текущую переменную из внешнего цикла, вторую - текущую переменную из вложенного цикла. Проверка на превосходство индекса во внутреннем цикле над индексом во внешнем требуется для того, чтобы сочетания не превращались в перестановки (т.е. чтобы исключалась возможность повторного вызова макроса с одной и той же парой переменных, идущих в другом порядке (например, var1 - var2 и var2 - var1)), а также чтобы исключить появление пар типа var1 - var1.

 

Программная реализация (запускающий макрос). Напомним, макрос в SPSS требуется сначала определить (выполнить код от команды DEFINE до !ENDDEFINE), а затем - запустить (один или несколько раз с одинаковыми или разными параметрами). Макрос принимает три параметра. Первый - !POS, позиционный. На него в макросе будем ссылаться как на !1 - он первый и единственный позиционный параметр. Он будет принимать список переменных, которые надо скомбинировать по парам. Хотя, вообще говоря, почему только переменные? Он может принимать какие угодно значения (например, строки), а это даёт разбираемому макросу ещё большее поле применения. Будем считать для определённости, что в этом аргументе будут содержаться имена переменных. Их может быть какое угодно количество. Имена переменных задаются через пробел. После последней переменной ставим символ "/" (!CHAREND('/')) - это даст SPSS знак, что приём первого параметра закончен. Второй параметр именной. Он содержит одну порцию информации (один токен). Подразумеваем, что здесь будет имя запускаемого макроса. Третий параметр, вообще говоря, необязателен. Он может быть передан в запускаемый макрос. Я привожу его здесь для полноты картины.

Тело макроса... Сначала сохраним данные (ведь вызываемый макрос может изменить их до неузнаваемости). Хорошо, кстати, проследить, чтобы вызываемый макрос ничего не писал в файл с характерным именем 'c:\temp\temp.sav'. :-)

В остальном задача проста. Нам передаются имена k переменных. Макрос должен сформировать из них Ck2 пар и для каждой пары запустить другой макрос. Соответственно, образующий элемент запускающего макроса - два вложенных цикла, о которых говорилось выше. Это циклы !DO ... !IN ... !DOEND. В параметре !IN в обоих случаях мы ссылаемся на список переменных (макроаргумент !1). Индекс внешнего цикла - макроаргумент !var1, внутреннего - !var2 - принимают последовательно имена переменных из !1. Внутри вложенного цикла - команда вызова макроса. Она не сразу угадывается: фактически, это функция !CONCAT на лету "раскавычивает" переданное имя запускаемого макроса, и вставляет через пробелы очередную пару имён переменных. Тут же мог найти своё место дополнительный параметр !par. Когда вызываемый макрос отработает, SPSS вновь загрузит рабочий файл данных ('c:\temp\temp.sav').

Остальное наполнение тела макроса - контроль того, чтобы внешний цикл "не догонял" внутренний, т.е. чтобы не появлялось дублирующих пар переменных. Для этого в каждом цикле установлены счётчики (!i1 для внешнего, !i2 для внутреннего), причём для внутреннего цикла этот счётчик сбрасывается в ноль при каждом его новом вызове: !LET !i2 = !NULL. Счётчики обновлять непросто. Поскольку макросы - лишь "генераторы кода", все аргументы в них фактически являются элементами этого кода, т.е. строками. Арифметические действия посредством операторов "+", "-", "/", "*" с ними невозможны. Вот и приходится наращивать счётчики добавлением одного пробела (!BLANK(1)) к уже существующей строке. Тогда совершенно логично считывать значение счётчика макрофункцией !LENGTH, измеряющей длину строки. В том случае, если порядковый номер переменной во внешнем цикле (!i1) оказывается меньше порядкового номера переменной во внутреннем (!i2), мы запускаем интересующий нас макрос.

Будем считать, что запускающий макрос мы разобрали.

DEFINE !comb (!POS=!CHAREND('/')
/macroname=!TOKENS(1)
/par=!CMDEND)

SAVE OUTFILE='c:\temp\temp.sav'.

!LET !i1=!NULL.

!DO !var1 !IN (!1)

- !LET !i2=!NULL.

- !LET !i1=!CONCAT(!i1,!BLANK(1)).

- !DO !var2 !IN (!1)

- !LET !i2=!CONCAT(!i2,!BLANK(1)).

- !IF (!LENGTH(!i2)>!LENGTH(!i1)) !THEN

- !CONCAT(!UNQUOTE(!macroname),' ',!var1,' ', !var2).

- GET FILE='c:\temp\temp.sav'.

- !IFEND.

- !DOEND.

!DOEND.

!ENDDEFINE.

 

Пример использования. Чтобы продемонстрировать действие только что определённого макроса, создадим совсем простой запускаемый макрос, строящий таблицу сопряжённости двух переменных. Без комментариев:

DEFINE !crtb (!POS=!TOKEN(1)
/!POS = !TOKEN(1))

CROSSTABS !1 BY !2.

!ENDDEFINE.

Теперь можно загрузить какой-нибудь файл данных:

GET FILE='Employee data.sav'.

...и запустить макрос:

!comb gender jobcat minority / macroname='!crtb'.

 

Всего доброго!

 

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

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

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

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

Завершён перевод раздела "Метки, имена и форматы переменных".

 

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


В избранное