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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
* Вопрос.
* Я знаю, как построить гистограммы для каждого из двух вузов с количеством студентов по оси Y и долларами по оси X (единица анализа - студент,  а переменная интереса - доллар).

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

* Ответ.
* Следующий (очень полезный) макрос поможет нам и в этом случае.
* Автор: rlevesque@videotron.ca.

* Идея приведённого синтаксиса в том, что вместо гистограммы строится столбцовая диаграмма (Bar Chart) со сконструированными определённым образом категориями. Таким образом, результирующий график напоминает гистограмму с процентами по оси Y - А.Б..

* NB! В "современных" версиях SPSS (например, 13 версия), проблема, указанная в вопросе, может быть решена с помощью интерактивных графиков (см. пример синтаксиса в конце файла). Если стоит отдельная задача создать интервалы для числовой переменной (что и делает макрос в этом файле), это удобно делать с помощью новой опции Visual Bander - А.Б.


*///////////////////////////////////////////////////////.
DEFINE !label (vname=!TOKENS(1)
                /vcoded=!TOKENS(1)
                /begr=!TOKENS(1)
                /endr=!TOKENS(1)
                /nbbins=!TOKENS(1))
* Загражаем данные, после чего запускаем этот макрос.
* vname 	= имя переменной, которую перекодируем.
* vcoded        	= имя переменной, которая будет содержать результат перекодировки.
* begr 		= начало первого интервала.
* endr  	= конец первого интервала (4 означает 4.99999...).
* nbbins        	= количество столбцов на гистограмме.
* nbbins, begr и endr должны быть целыми значениями.
* Автор: Raynald Levesque rlevesque@videotron.ca.

SAVE OUTFILE='C:\\temp\\data temp zz1z.sav'.
NEW file.
INPUT PROGRAM.
LOOP id=1 TO !nbbins.
+COMPUTE #delta=1+ !endr - !begr.
+DO IF id=1.
++COMPUTE begv=!begr.
++COMPUTE endv=begv + #delta.
++ELSE.
++COMPUTE begv=LAG(begv)+#delta.
++COMPUTE endv=LAG(endv) + #delta.
+END IF.
+END CASE.
END LOOP.
END FILE.
END INPUT PROGRAM.
STRING vname(A8).
COMPUTE vname=!QUOTE(!EVAL(!vname)).
COMPUTE dummy=0.
MATCH FILES FILE=* /BY dummy /LAST=last.
STRING vcoded(A8).
COMPUTE vcoded=!QUOTE(!EVAL(!vcoded)).
FORMATS id begv endv (F8.0).

* создаём файл синтаксиса для перекодировки значений.
DO IF $CASENUM=1.
WRITE OUTFILE="c:\\temp\\recode values1.sps"/"RECODE " vname " (" begv " THRU" endv " = " id " )".
ELSE.
WRITE OUTFILE="c:\\temp\\recode values1.sps"/" (" begv " THRU " endv " = " id" )".
END IF.
DO IF last.
WRITE OUTFILE="c:\\temp\\recode values1.sps"/" INTO " vcoded  ". ".
END IF.

* пишем синтаксис для определения меток значений.
COMPUTE endv=RND(endv).
STRING q1(A1) /label1(A14).
COMPUTE q1="'".
COMPUTE label1=CONCAT(LTRIM(STRING(begv,F8.0))," -",LTRIM(STRING(endv,F8.0))).
WRITE OUTFILE="c:\\temp\\recode values2.sps"
        /"ADD VALUE LABELS " vcoded  id " " q1 label1 q1 ".".
EXECUTE.

GET FILE='C:\\temp\\data temp zz1z.sav'.
INCLUDE "c:\\temp\\recode values1.sps".
INCLUDE "c:\\temp\\recode values2.sps".
SET TNUMBERS=LABELS /TVARS=LABELS.
VARIABLE LABEL !vcoded !QUOTE(!vname).
EXECUTE.

!ENDDEFINE.
*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\.


* Сгенерируем данные для демонстрации работы решения.
INPUT PROGRAM.
SET SEED=9876531.
LOOP school=1 TO 2.
LEAVE school.
LOOP id=1 TO school*50.
COMPUTE dollars=7000+UNIFORM( 10000).
* следующая строка создаёт "пробел" (пустой столбец) в данных для демонстрации возможной проблемы и возможного решения.
IF RANGE(dollars,11999,13001) dollars=dollars-1000.
END CASE.
END LOOP.
END LOOP.
END FILE.
END INPUT PROGRAM.

* осуществляем перекодировку значений и помечаем новые коды.
!label vname=dollars vcoded=dollar2 begr=7000 endr=7999 nbbins=11.

SORT CASES BY school .
SPLIT FILE LAYERED BY school .

* Метод 1.
GRAPH
  /TITLE='Метод 1, пустые столбцы не печатаются'
  /BAR(SIMPLE)=PCT BY dollar2
  /MISSING=REPORT.

* Method 2.

SPLIT FILE OFF.
AGGREGATE
  /OUTFILE='c:\\temp\\temp01.sav'
  /BREAK=school
  /totcases = N(id).

AGGREGATE
  /OUTFILE=*
  /BREAK=school dollar2
  /nbcases = N(id).

MATCH FILES /FILE=*
 /TABLE='C:\\Temp\\temp01.sav'
 /BY school.

* Заполняем "пропуски" таким образом, чтобы столбцы выводились на график даже если они пустые.
DO IF $casenum=1.
+ LOOP sch=1 TO 2.
+ LOOP varx=1 TO 11.
+ XSAVE OUTFILE='c:\\temp\\temp02.sav' /KEEP=varx sch.
+ END LOOP.
+ END LOOP.
END IF.
EXECUTE.
SORT CASES BY school dollar2.
MATCH FILES FILE=* /DROP=varx sch.
MATCH FILES FILE=* /FILE='c:\\temp\\temp02.sav' 
 /RENAME= (varx=dollar2) (sch=school) /BY school dollar2.
EXECUTE.

DO IF MISSING(nbcases).
COMPUTE totcases=1.
COMPUTE nbcases=1E-30.
END IF.
COMPUTE pc=nbcases/totcases.

SORT CASES BY school .
SPLIT FILE LAYERED BY school .
FORMATS pc(PCT8.1).
GRAPH
  /TITLE='Метод 2, пустые столбцы печатаются'
  /BAR(SIMPLE)=VALUE( pc ) BY dollar2 .


* В версии 13 SPSS такая задача может быть решена непосредственно без помощи макросов через меню интерактивных графиков:
IGRAPH /VIEWNAME='Histogram' /X1 = VAR(dollars) TYPE = SCALE /Y = $pct /COORDINATE = VERTICAL /PANEL VAR(school)
 /X1LENGTH=3.0 /YLENGTH=3.0 /X2LENGTH=3.0 /CATORDER VAR(school)
 (ASCENDING VALUES OMITEMPTY) /Histogram  SHAPE = HISTOGRAM CURVE = OFF X1INTERVAL AUTO X1START = 0.