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
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
* (Вопрос) Нужно найти все сочетания 1, 2, ..., n объектов из m объектов.

* (Ответ) Автор: rlevesque@videotron.ca, 30.08.2001;
	Сайт, посвящённый SPSS: http://www.spsstools.net.

* Заметка: Это достаточно сложный синтаксис, который, впрочем, очень прост в использовании. Макрос n раз создаёт новый файл синтаксиса, который записывает сочетания в текстовый файл. Затем этот файл читается в редактор данных SPSS и используется для создания полного списка сочетаний.
* См. пример использования в конце.


SET MPRINT=no.

*/////////////////////////////.
DEFINE !combine (n=!TOKENS(1) 
	/items=!CMDEND).

/* Ищем все сочетания 1,2, ... n объектов из m объектов*/
/* 30 августа 2001 года, rlevesque@videotron.ca */

* Считаем количество переданных переменных.
!LET !nb=!NULL
!DO !cnt !IN (!items)
!LET !nb=!CONCAT(!nb,!BLANK(1))
!DOEND
!LET !m=!LENGTH(!nb)

!DO !thisn=1 !TO !n
NEW FILE.
INPUT PROGRAM.
LOOP i=1 TO !thisn.
END CASE.
END LOOP.
END FILE.
END INPUT PROGRAM.
LIST.

!LET !list=!NULL
!DO !cnt=1 !TO !thisn
	!LET !list=!CONCAT(!list," ","j",!cnt)
!DOEND

COMPUTE n=!thisn.

* Получим имена переменных для цикла LOOP в команде WRITE ниже *.
STRING cntname cntbeg(A8).

COMPUTE cntname=CONCAT('j',LTRIM(STRING(i,F8.0))).

* Получим первый параметр для цикла LOOP в команде WRITE ниже *.
DO IF i=1.
COMPUTE cntbeg="1".
ELSE.
COMPUTE cntbeg=CONCAT('j',LTRIM(STRING(i-1,F8.0))," + 1").
END IF.

* Получим второй параметр для цикла LOOP в команде WRITE ниже *.
COMPUTE k=!m - !thisn + i.
FORMATS i k n(F8.0).

STRING quote(A1) strlist(A255).
COMPUTE quote='"'.
COMPUTE strlist=!QUOTE(!list).

* Запишем файл синтаксиса, который затем будет писать все сочетания в текстовый файл list.txt*.
WRITE OUTFILE "c:\\temp\\macro.sps" 
	/"LOOP "cntname"="cntbeg" TO "k".".
DO IF i=!thisn.
+	WRITE OUTFILE "c:\\temp\\macro.sps" 
	/"WRITE OUTFILE "quote"c:\\temp\\list.txt"quote "/" strlist "." .
+	LOOP cnt=1 TO !thisn.
+		WRITE OUTFILE "c:\\temp\\macro.sps" /"END LOOP.".
+	END LOOP.
+	WRITE OUTFILE "c:\\temp\\macro.sps" /"EXECUTE.". 
END IF.
EXECUTE.
INCLUDE FILE="c:\\temp\\macro.sps".

/* Конвертируем данные из файла list.txt в соответствующий .sav файл */.
DATA LIST FILE='c:\\temp\\list.txt' LIST /!list.
SAVE OUTFILE=!QUOTE(!CONCAT('c:\\temp\\list',!thisn,'.sav')).
!DOEND

/* Собираем все .sav-файлы в один */.
GET FILE='c:\\temp\\list1.sav'.
!DO !nb=2 !TO !n.
ADD FILES FILE=* 
	/FILE=!QUOTE(!CONCAT('c:\\temp\\list',!nb,'.sav.')).
!DOEND

/* Убираем дубликаты  */.
SORT CASES BY ALL.
MATCH FILES FILE=* /BY=ALL /FIRST=first.
SELECT IF first.
SAVE OUTFILE='c:\\temp\\all combinations.sav'.

/* Ищем имя последнего объекта */
!DO !var !IN (!items)
!LET !lastone=!var
!DOEND

VECTOR vnames(!m A8).
!LET !cnt=!BLANK(1)

/* Создаём переменные, содержащие названия объектов */
!DO !var !IN (!items)
COMPUTE vnames(!LEN(!cnt))=!QUOTE(!var).
!LET !cnt=!CONCAT(!cnt,!BLANK(1))
!DOEND

/* Создаём строку, содержащую список сочетаний */.
STRING items(A255).
VECTOR j=j1 TO !CONCAT('j',!n) /ind=vnames1 TO  !CONCAT('vnames',!m).
COMPUTE nvar=NVALID(j1 TO !CONCAT('j',!n)).
LOOP cnt=1 TO nvar.
COMPUTE items=CONCAT(RTRIM(items)," ",vnames(j(cnt))).
END LOOP.

EXECUTE.

!ENDDEFINE.
*////////////////////////////.


*************************.
* Примеры использования.
*************************.

SET MPRINT=yes.
!combine n=5 items=educ jobcat jobtime prevexp minority.

* Example 2.
!combine n=3 items=a b c d e f g.