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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
/* Синтаксис рассчитывает следующие индексы неравенства (неравномерности распределения ресурсов):
 - индекс Аткинсона (ATKINSON) = коэффициент спроса.
 - энтропийный индекс Тейла (показатель избыточности, THEIL redundancy).
 - коэффициент резервов (RESERVE coefficient).
 - коэффициент D&R = коэффициент Кульбака-Лейблера.
 - показатель избыточности Кульбака-Лейблера (KULLBACK-LIEBLER redundancy).
 - коэффициент Хувера (HOOVER coefficient).
 - коэффициент Коултера (COULTER coefficient).
 - индекс Джини (GINI coefficient).

 Строится кривая Лоренца.
 В случае, если имеются данные более, чем за 1 год, на графике выводятся разные индексы.
 В конце файла находятся 9 примеров того, как пользоваться определяемыми здесь макросами.
 Это решение распространяется свободно.
 Автор: Raynald Levesque, rlevesque@videotron.ca.*/.


* Использованные формулы в синтаксисе SPSS были взяты с сайта Готца Клуджа (Goetz Kluge) (17 февраля 2001 года).
* Адрес: http://poorcity.richcity.org/ .
* За комментариями по различным показателям неравенства и информацией по их применению, 
* пределам изменения показателей, их значимости, ссылками на литературу обращайтесь к этой
* веб-странице.

* Что касается кривой Лоренца...
* Кривая Лоренца отображает накопленную долю дохода против накопленной доли численности населения.
* Диагональ означает идеально равномерное распределение дохода. Чем больше кривая Лоренца отклоняется
* от диагонали, тем более неравномерно распределены доходы в обществе. Обилие различных математических
* разработок, связанных с кривой Лоренца, сделали её, фактически, символом измерения и анализа неравенства.
* См. http://www.worldbank.org/poverty/inequal/.

* Рекомендации по использованию.
* 1. Сохраните 2 макроса в отдельный файл sps (скажем, inequality.sps).
* 2. Один раз за сессию работы с SPSS определите макрос, использую команду INCLUDE. 
* 3. Сохраните шаблон графика inequality.sct в папку по вашему выбору, соответственно измените путь в inequality.sps.
*    (При использовании SPSS до версии 12.0. Для новых версий потребуется создать другой шаблон - примеч. перев.)
* 4. Синтаксис предполагает, что папка "c:\\temp\\" существует.
* 4. См. примеры использования в конце синтаксиса.

* Замечания.
* 1. Наблюдения с пропущенными значениями дохода исключаются.
* 2. Синтаксис может работать с файлами данных за разные годы. Для каждого файла (каждого года)
     синтаксис вычисляет коэффициенты, а затем строит график со всеми коэффициентами, на котором
     видно, как они меняются со временем.
     
SET MPRINT=yes /PRINTBACK=listing /RESULTS=listing.

*////////////////////////////////////////////.
DEFINE !inequal (sal	=!TOKENS(1) 
		/data	=!DEFAULT('i') !TOKENS(1)
		/ntiles	=!DEFAULT('0') !TOKENS(1)
		/yr	=!TOKENS(1))

* data=i означает, что исходные данные даются на уровне индивидов
* data=g означает, что исходные данные уже сгруппированы (для каждой группы дана её численность и суммарный доход)
* data=w означает, что данные представлены во взвешенном виде (вес находится в переменной "a")
* ntiles=0 группируем данные по отдельным значениям переменной дохода.
* ntiles>0 группируем данные по интервалам значений переменной дохода, ntiles - число интервалов.

COMPUTE dummy=1.		

!IF (!data !NE 'g') !THEN

* Взвешиваем данные если требуется.
!IF (!data !EQ 'w') !THEN
WEIGHT BY a.
!IFEND

* Исключаем наблюдения с пропущенными значениями !sal.
SELECT IF ~MISSING(!sal).

!IF (!ntiles !NE '0') !THEN
* Разбиваем данные на ntiles групп.
!LET !brkvar=nsal
RANK
  VARIABLES=!sal  (A) /NTILES (!ntiles) INTO !brkvar /PRINT=YES
  /TIES=MEAN .
!ELSE
* Группируем данные по значениям !sal.
!LET !brkvar=!sal
!IFEND

* Находим итоги для групп.
AGGREGATE
  /OUTFILE='C:\\temp\\AGGR as needed.SAV'
  /BREAK=!brkvar
  /ai = N(!sal) /ei = SUM(!sal) /dummy=FIRST(dummy).

* Находим общие итоги.
AGGREGATE
  /OUTFILE=*
  /BREAK=dummy
  /atot = N(!sal) /etot = SUM(!sal).

* Добавляем общие итоги к файлу с итогами по группам.
MATCH FILES /TABLE=*
 /FILE='C:\\Temp\\AGGR as needed.SAV'
 /BY dummy.
SORT CASES BY !brkvar(A).
!IFEND

!IF (!data !EQ 'g') !THEN
* данные уже сгруппированы. Осталось найти общие итоги и добавить их к файлу.
AGGREGATE
  /OUTFILE='C:\\Temp\\AGGR as needed.SAV'
  /BREAK=dummy
  /atot = SUM(ai) /etot = SUM(!sal).
MATCH FILES /FILE=*
 /TABLE='C:\\Temp\\AGGR as needed.SAV'
 /BY dummy.
!IFEND

***********************.
* 
* Вычисляем коэффициенты и показатели избыточности.
*
***********************.

* Считаем индекс Аткинсона = коэффициент спроса.
COMPUTE demand1=ei*LN(ai/ei)/etot.
CREATE demand2=CSUM(demand1).
COMPUTE zdemand=1-EXP(demand2)*etot/atot.

* Считаем показатель избыточности Тейла.
COMPUTE rtheil=-LN(1-zdemand).

* Считаем коэффициент резервов.
COMPUTE reserv1=ai*LN(ei/ai)/atot.
CREATE reserv2=CSUM(reserv1).
COMPUTE zreserve=1-EXP(reserv2)*atot/etot.

* Считаем коэффициент D&R (Кульбака-Лейблера).
COMPUTE zd_and_r=1-SQRT((1-zdemand)*(1-zreserve)).

* Считаем показатель избыточности Кульбака-Лейблера.
COMPUTE rkull_li=-LN(1-zd_and_r).

* Считаем коэффициент Хувера.
COMPUTE hoover1=ABS(ei/etot-ai/atot).
CREATE hoover2=CSUM(hoover1).
COMPUTE zhoover=hoover2/2.

* Считаем коэффициент Коултера.
COMPUTE coulte1=(ei/etot - ai/atot)**2.
CREATE coulte2=CSUM(coulte1).
COMPUTE zcoulter=SQRT(coulte2/2).

* Считаем коэффициент Джини.
CREATE csai csei=CSUM(ai ei).
COMPUTE gini1=(2*csei-ei)*ai/(etot*atot).
CREATE gini2=CSUM(gini1).
COMPUTE zgini=1-gini2.

* Выводим значения показателей неравенства.
MATCH FILES FILE=* /BY dummy /LAST=last.
TEMPORARY.
SELECT IF last.
!LET !title=!QUOTE(!CONCAT('Итоговые коэффициенты и показатели избыточности',!UNQUOTE(!yr)))
SUMMARIZE
  /TABLES=zdemand rtheil zreserve zd_and_r rkull_li zhoover zcoulter zgini 
  /FORMAT=VALIDLIST NOCASENUM TOTAL
  /TITLE=!title
  /MISSING=VARIABLE
  /CELLS=NONE.

* Выводим информацию для групп.
COMPUTE pccsei=csei/etot*100.
COMPUTE pccsai=csai/atot*100.
COMPUTE refline=pccsai.
COMPUTE avg=ei/ai.
FORMATS avg ei(COMMA12.0) pccsai pccsei (PCT6.1).
!LET !title=!QUOTE(!CONCAT('Информация по группам', !UNQUOTE(!yr)))
SUMMARIZE
  /TABLES=ai ei avg pccsai pccsei
  /FORMAT=VALIDLIST NOCASENUM TOTAL
  /TITLE=!title
  /MISSING=VARIABLE
  /CELLS=NONE.

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

* Создадим фиктивное наблюдение с нулевыми значениями для следующих 3 переменных:.
NEW FILE.
INPUT PROGRAM.
COMPUTE pccsai=0.
COMPUTE pccsei=0.
COMPUTE refline=0.
END CASE.
END FILE.
END INPUT PROGRAM.
LIST.

* Добавим это фиктивное наблюдение к файлу данных, чтобы график кривой Лоренца начинался из точки (0,0).
ADD FILES /FILE=*
 /FILE='C:\\temp\\temp2.sav'.
FORMATS pccsai pccsei refline (PCT6.0).
!LET !title=!QUOTE(!CONCAT('Кривая Лоренца ',!UNQUOTE(!yr)))
GRAPH
  /TITLE=!title
  /TEMPLATE='c:\\Program Files\\SPSS\\syntax\\inequality\\inequality.sct'
  /SCATTERPLOT(OVERLAY)= pccsai pccsai WITH pccsei refline  (PAIR)
  /MISSING=LISTWISE .

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


* ##### ПРИМЕР 1.
* Предварительно сгруппируем людей по значениям переменной salary на 20 групп.
GET  FILE='C:\\Program Files\\SPSS\\University of Florida graduate salaries.sav'.
!inequal sal=salary ntiles=20. 

* ##### ПРИМЕР 2.
* Группировка идёт по отдельным значениям переменной salary.
GET  FILE='C:\\Program Files\\SPSS\\University of Florida graduate salaries.sav'.
!inequal sal=salary. 

* ##### ПРИМЕР 3.
* Используем взвешивание данных.
* Здесь 20 людей зарабатывают по 20 единиц каждый, 10 - по 30 единиц и т.д.
DATA LIST LIST /a e.
BEGIN DATA
20 20
10 30
5 40
5 50
END DATA.

!inequal sal=e data=w.

* ##### ПРИМЕР 4.
* Используем теперь предварительно сгруппированные данные (по сути, это те же данные, что представлены выше,
  но иначе организованные).
* Здесь 20 беднейших индивидов имеют суммарный доход 400 единиц, а 5 богатейших - суммарный доход 250 единиц.
DATA LIST LIST /ai ei.
* Число наблюдений и суммарный доход в группах должны содержаться, 
* соответственно, в переменных ai и ei.
BEGIN DATA
20 400
10 300
5 200
5 250
END DATA.

!inequal sal=ei data=g.
* Данные, приведённые выше, взяты с http://poorcity.richcity.org/. Полученные в примере 4
* коэффициенты совпадают с размещёнными на сайте.


*######################################.

* Следующая часть синтаксиса предназначена для обработки файлов с информацией за несколько лет.
* Программа сначала вычисляет все коэффициенты для каждого файла, используя вышеопределённый макрос.
* Затем она на графике показывает динамику каждого коэффициента (например, индекса Джини) по годам.
*######################################.

*///////////////////////////////////.
DEFINE !manyyrs (sal=!TOKENS(1) 
		/data= !DEFAULT('i') !TOKENS(1)
		/ntiles= !DEFAULT('0') !TOKENS(1)
		/fname=!TOKENS(1)
		/nbyrs=!TOKENS(1))

* Первые 3 параметра необходимы для вызова макроса inequal, определённого выше.
* Параметр fname содержит путь с буквенной частью имени файла (пр.: "c:\\mydata").
* Параметр nbyrs содержит число разных файлов данных
* Например, nbyrs=3, fname=c:\\mydata. Тогда на диске должно быть 3 файла:
* mydata1.sav, mydata2.sav и mydata3.sav.

!DO !cnt=1 !TO !nbyrs
GET FILE=!QUOTE(!CONCAT(!UNQUOTE(!fname),!cnt,'.sav')).
!LET !thisyr=!QUOTE(!CONCAT(', Year=',!cnt))
!inequal sal=!sal data=!data ntiles=!ntiles yr=!thisyr.

SELECT IF last.
COMPUTE yr=!cnt.
FORMATS yr(F8.0).
!IF (!cnt=1) !THEN 
SAVE OUTFILE=!QUOTE(!CONCAT(!UNQUOTE(!fname)," summary.sav")).
!ELSE
ADD FILES FILE=* 
	/FILE=!QUOTE(!CONCAT(!UNQUOTE(!fname)," summary.sav")).
SAVE OUTFILE=!QUOTE(!CONCAT(!UNQUOTE(!fname)," summary.sav")).
!IFEND

!DOEND
EXECUTE.
GET FILE=!QUOTE(!CONCAT(!UNQUOTE(!fname)," summary.sav")).

SORT CASES BY yr.
SUMMARIZE
  /TABLES=yr zdemand rtheil zreserve zd_and_r rkull_li zhoover zcoulter zgini 
  /FORMAT=VALIDLIST NOCASENUM TOTAL
  /TITLE='Итоговые коэффициенты и показатели избыточности (по годам)'
  /MISSING=VARIABLE
  /CELLS=NONE.

GRAPH
  /TITLE="Первые 4 коэффициента"
  /LINE(MULTIPLE)= VALUE( zdemand rtheil zreserve zd_and_r ) BY yr.
GRAPH
  /TITLE="Последние 4 коэффициента"
  /LINE(MULTIPLE)= VALUE( rkull_li zhoover zcoulter zgini ) BY yr.
GRAPH
  /TITLE="Все 8 коэффициентов"
  /LINE(MULTIPLE)= VALUE(zdemand rtheil zreserve zd_and_r rkull_li zhoover zcoulter zgini ) BY yr.

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



****************************.

* Теперь напишем макрос, который создаст 12 файлов с фиктивными данными просто для того,
* чтобы проверить работу макроса manyyrs.

****************************.


*///////////////////////////.
DEFINE !dummy().
!DO !yr=1 !TO 12.
INPUT PROGRAM.
LOOP linenb=1 TO 10.
COMPUTE a=15+TRUNC(UNIFORM(15)+1).
* Файлы создаются таким образом, чтобы распределение доходов с течением времени становилось
* всё менее равномерным.
COMPUTE e=20+!yr*linenb*2+UNIFORM(3).
END CASE.
END LOOP.
END FILE.
END INPUT PROGRAM.
LIST.
SAVE OUTFILE=!QUOTE(!CONCAT("c:\\temp\\testfile",!yr,".sav")).
!DOEND.
!ENDDEFINE.
*///////////////////////////.


* ##### ПРИМЕР 5.
* Следующей командой просто создаём 12 фиктивных файлов данных (как бы за 12 лет).
!dummy.
* Запускаем макрос со всеми 12 файлами и выводим на график все 8 коэффициентов за 12 лет.
!manyyrs sal=e data=w fname="c:\\temp\\testfile" nbyrs=12.

* ##### ПРИМЕР 6.
* Этот пример использует файл SAMPLH.SAV исследования LIS (см. http://www.lisproject.org/dataccess/spss_samplefiles.htm).
* Веса и доходы берутся прямо из файла данных.
GET FILE='D:\\data\\aa\\Luxemb\\samplh.sav' /KEEP=d5 hweight casenum dpi.
SELECT IF d5 NE 2.
COMPUTE a=hweight.
!inequal sal=dpi data=w ntiles=100.

* ##### ПРИМЕР 7.
* Этот пример использует файл SAMPLH.SAV исследования LIS (см. http://www.lisproject.org/dataccess/spss_samplefiles.htm).
* Веса и доходы вычисляются.
GET FILE='D:\\data\\aa\\Luxemb\\samplh.sav' /KEEP=d4 d5 d27 hweight casenum dpi.
SELECT IF d5 NE 2.
COMPUTE a=hweight*d4.
COMPUTE oecdeq=(1+(.5*d27)+(.7*(d4-d27-1)))/2.2.
COMPUTE y=dpi/oecdeq.
!inequal sal=y data=w ntiles=100.

* ##### ПРИМЕР 8.
* Подготовим данные к анализу (будут анализироваться файлы FI91H и FI95H).
* Создадим 2 фиктивных файла, как будто это данные по Финляндии за 2 года.
GET FILE='D:\\data\\aa\\Luxemb\\samplh.sav' /KEEP=d4 d5 d27 hweight casenum dpi.
SAVE OUTFILE='c:\\temp\\FI91h.sav'.
* Извлечение квадратного корня из dpi симулирует снижение неравенства.
COMPUTE dpi=SQRT(dpi).
SAVE OUTFILE='c:\\temp\\FI95h.sav'.

* Начало примера.
GET FILE='c:\\temp\\FI91h.sav' /KEEP=d4 d5 d27 hweight casenum dpi.
SELECT IF d5 NE 2.
COMPUTE income=dpi.
COMPUTE a=hweight.
SAVE OUTFILE='c:\\temp\\FI1.sav'.
SELECT IF $casenum=0.

ADD FILES FILE='c:\\temp\\FI95h.sav' /KEEP=d4 d5 d27 hweight casenum dpi.
SELECT IF d5 NE 2.
COMPUTE income=dpi.
COMPUTE a=hweight.
SAVE OUTFILE='c:\\temp\\FI2.sav'.

* Анализируем данные по Финляндии за 2 года.
!manyyrs sal=income ntiles=100 data=w fname="c:\\temp\\FI" nbyrs=2.

* ##### ПРИМЕР 9.
* Алгоритм из 8-го примера может быть использован для сравнения нескольких стран.
* Например, файл 
CO1.sav можно назвать FI95
CO2.sav можно назвать US94
CO3.sav можно назвать GE94
CO4.sav можно назвать SW95.
* Следующий вызов макроса сравнит сразу 4 страны.
!manyyrs sal=income ntiles=100 data=w fname="c:\\temp\\CO" nbyrs=4.