С мая 2006 года сервис Subscribe.Ru предоставляет получателям
HTML-версий рассылок возможность голосования за очередной выпуск (через сайт,
либо письмом). В нижнем и верхнем колонтитулах каждого выпуска вы найдёте шкалу
для голосования по 5-балльной шкале (где 5 означает наивысший балл). Я просил
бы вас по возможности выражать своё мнение относительно содержания, оформления,
стиля, полезности полученного вами выпуска в виде этой комплексной оценки. Я
могу просматривать полученную статистику оценок по выпускам и анализировать
собственную работу. Надеюсь, это позволит сделать рассылку более информативной
и практически полезной. Возможно, в будущем я сделаю специальный вопросник,
в котором вы сможете дать развёрнутую оценку данной рассылки, но пока я буду
рад получать сжатую оценочную информацию. Разумеется, большое количество хороших
оценок с вашей стороны положительно отразится на рейтинге рассылки, но, наверное,
это не главное. Комментарии вы всегда можете направить мне на a-balabanov( at)
yandex.ru.
Удаление переменных по списку
Это будет короткий выпуск. Рассмотрим небольшой, но изящный в
своей простоте и функциональности макрос, позволяющий удалять переменные по
списку, независимо от того, существуют они в файле данных, или нет.
Вопрос-задание звучал следующим образом: "Требуется очистить
файл данных от переменных, которые были созданы ранее исполнявшимся синтаксисом.
Я знаю имена всех возможных переменных, которые нужно удалить, но не всякий
раз все из них присутствуют в файле". Допустим, у нас есть следующие данные:
DATA LIST LIST/ id acol01 var var2 bcol02.
BEGIN DATA
1 3 5 7 9
2 3 4 5 8
3 4 3 4 6
END DATA.
Предположим, эти данные - результат выполнения ряда трансформаций,
в ходе которых было добавлено несколько переменных. Причём это - лишь один из
нескольких вариантов преобразований, в ходе которых могли быть добавлены следующие
переменные, известные пользователю по именам: acol01, acol02,
bcol01, bcol02. Как видно из перечня, в данном случае в файле
имеются лишь acol01 и bcol02. Чтобы не отслеживать всякий
раз наличие тех или иных переменных, удобно было бы иметь команду, которая очищает
файл данных от всех лишних, служебных переменных из предоставленного ей списка,
самостоятельно выбирая из него лишь те переменные, которые есть в данный момент
в файле.
не проходят, так как фактическое отсутствие в файле хотя бы одной
переменной из списка приведёт к ошибкам, в результате которых ни одна переменная
не будет удалена*.
*Напомню, что, хотя в языке SPSS существует специальная команда
удаления переменных (DELETE VARIABLES, или DEL VARS), на практике часто используют
команды функционально иного назначения, но в определённой спецификации дающие
тот же эффект. Например, команды объединения файлов ADD FILES и MATCH FILES
c ключевым словом DROP. ADD FILES имеет над остальными командами то преимущество,
что является процедурой, запускающей проход по данным: нет нужны предварять
удаление переменных выполнением отложенных ранее вычислений с помощью дополнительной
инструкции EXECUTE.
Конечно, возможны варианты вроде
ADD FILES FILE=* /DROP acol01.
ADD FILES FILE=* /DROP acol02.
ADD FILES FILE=* /DROP bcol01.
ADD FILES FILE=* /DROP bcol02.
(то есть, выделение "своей" команды каждой переменной
из списка). Это рабочий вариант. Переменные, присутствующие в файле, будут удалены,
а отсутствующие будут вызывать ошибки, которые, впрочем, не отразятся на выполнении
остальных команд (для других переменных).
Но макроязык SPSS даёт нам возможность написать свою короткую
"команду" удаления переменных, лишённую недостатков стандартных вариантов
ADD FILES или DEL VARS.
Определим следующий макрос:
DEFINE !delete(!POS=!CMDEND)
!DO !var !IN(!1)
ADD FILES FILE=* /DROP=!var.
!DOEND
!ENDDEFINE.
...и разберём принцип его действия. Макрос содержит единственный
позиционный параметр (ссылка на него будет осуществляться как на !1, так как
этот параметр - первый и единственный в данном макросе). Параметр вбирает в
себя всё, что указано при вызове макроса до точки (окончания команды) - на это
указывает ключевое слово !CMDEND. Подобный способ позволяет передать за один
вызов макроса большой список переменных для проверки и удаления.
Само "тело" макроса содержит единственный цикл !DO
- !DOEND, задача которого - сгенерировать необходимое число команд ADD FILES
(по числу переданных имён переменных), подставляя всякий раз в подкоманду DROP
имя очередной переменной. В результате развёртывания (expansion) макроса для
исполнения SPSS принимает синтаксис, эквивалентный приведённому выше: для каждой
переменной сформирована своя "персональная" команда ADD FILES. При
исполнении синтаксиса попытка удаления отсутствующих переменных будет вызывать
ошибки, но за счёт независимости команд цель в итоге будет достигнута - лишние
переменные будут удалены. Разумеется, в теле цикла на место ADD FILES могла
бы быть подставлена команда DEL VARS.
Что здесь может смутить пользователя... Может возникнуть ассоциация
позиционного параметра с номером переданной переменной из списка. Дескать, !1
означает acol01, !2 - acol02, и т.д. Это не так. Параметр
единственный (!1), хотя и включающий в себя несколько порций информации - несколько
"токенов". Чтобы нам пробежать по всем из них в макросе и используется
цикл !DO - !DOEND с индексной макропеременной !var, которая последовательно
принимает все значения из множества токенов параметра - !IN(!1).
Напомним, что использование макроса включает его однократное
определение (с возможностью последующих переопределений) и многократное (в рамках
текущей сессии SPSS) использование. Выше макрос был определён. А теперь мы его
вызовем для примера. Непосредственно перед вызовом макроса мы включаем его распечатку
на экран (set mprint=yes), чтобы видеть, какие именно команды сгенерировал макрос.
Если у вас включена опция листинга в окне результатов SPSS, вы увидите сформированный
макросом синтаксис в строках после значков "M>".
set mprint=yes.
!delete acol01 acol02 bcol01 bcol02.
Задача решена. У нас есть единственная (макро)команда, которая
принимает список переменных и удаляет те переменные в файле данных, которые
присутствуют в этом списке. Вызов этого макроса может завершать длинный перечень
команд преобразований, удаляя ненужные пользователю (временные) переменные.
В заключение выпуска - комментарий к вопросу выпуска предыдущего.
В чём причина того, что разбираемый макрос не может обрабатывать отрицательные
коды категорий? Ответ становится очевидным при взгляде на синтаксис, генерируемый
макросом. Если бы, например, в переменной jobcat из рассмотренного
примера была категория -1, и мы бы указали постоянную часть имени двоичной переменной
job, в синтаксис, формируемый макросом для записи во внешний файл в
какой-то момент была бы записана команда на создание переменной с именем job-1,
однако SPSS не поддерживает имена переменных с дефисом. Преобразование числового
значения в текстовое, производимое макросом ранее, сохранило знак "минус"
и сделало невозможным создание соответствующей двоичной переменной. При необходимости
макрос может быть доработан с учётом этой особенности.