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
* Переход от 2 файлов к одному файлу с одним наблюдением на id.
* Это требуется, например, если в одном файле у вас какая-та общая информация о пациентах,
а в другом файле, скажем, результаты их анализов на разные даты. Причём неизвестно, сколько 
анализов может быть максимально у отдельно взятого пациента.
Данный синтаксис сам определяет это максимальное число записей на пациента и адаптирует 
число необходимых столбцов (переменных) в новом файле, после чего - сливает файлы
таким образом, что информация обо всех анализах у каждого пациента вытянута в строку.

* Автор: Raynald Levesque, rlevesque@videotron.ca.


* ------------ Во-первых, создадим кое-какие данные для примера.

DATA LIST LIST /id(F8) vara(F8) varb(F8).
BEGIN DATA.
1 10 12
2 15 17
3 10 20
4 20 30
END DATA.
LIST.
SAVE OUTFILE='c:\\temp\\id data.sav'.

DATA LIST LIST /id(F8) date1(ADATE) test(F8).
BEGIN DATA.
1  10/1/99 1
1 11/2/99 2
1 12/12/99 2
2 1/1/99 1
2 2/1/99 3
3 3/1/99 1
3 4/1/99 2
3 5/1/99 4
3 6/1/99 5
END DATA.
LIST.
SAVE OUTFILE='c:\\temp\\tests data.sav'.

* ------------------	Теперь определим максимальное число наблюдений на id, 
* ------------------	после чего создадим макрос, который будет содержать это число.
* ------------------	Затем включим этот макрос в рабочий синтаксис.

RANK test BY id /N INTO n.
COMPUTE dummy=1.

AGGREGATE
  /OUTFILE=*
  /BREAK=dummy
  /n = MAX(n).

WRITE OUTFILE 'c:\\temp\\temp.sps' /"DEFINE !n()" n "!ENDDEFINE.".
EXECUTE.
INCLUDE 'c:\\temp\\temp.sps'.

* ------------------	Теперь выполняем преобразования.

* Нумеруем строки внутри одного id.
GET
  FILE='c:\\temp\\tests data.sav'.
DO IF $CASENUM=1.
COMPUTE case_nb=1.
ELSE IF id=LAG(id).
COMPUTE case_nb=LAG(case_nb)+1.
ELSE.
COMPUTE case_nb=1.
END IF.

* Распределеяем значения наблюдений по соответствующим колонкам.
VECTOR tests(!n F8.0) dates(!n ADATE8).
COMPUTE dates(case_nb)=date1.
COMPUTE tests(case_nb)=test.

* Определим макрос, который "сожмёт" информацию из разных строк в единую строку на каждый id.
DEFINE !agg (numb=!TOKENS(1)).
AGGREGATE
  /OUTFILE=*
  /BREAK=id
  /test1 TO !CONCAT('test',!numb) =MAX(tests1 TO !CONCAT('tests',!numb)) 
  /date1 TO !CONCAT('date',!numb) =MAX(dates1 TO !CONCAT('dates',!numb)) .
!ENDDEFINE.

*Вызовем макрос и получим одну строку на id.
!agg numb=!n.

* Теперь - сольём 2 файла.
MATCH FILES /FILE=*
 /FILE='c:\\temp\\id data.sav'
 /BY id.
EXECUTE.