* Пропорциональный отбор без возвращения. * Городские кварталы имеют разное число жителей. Требуется реализовать случайную выборку кварталов, причём вероятность отбора должна быть пропорциональна населённости квартала. * (фактически, отбор реализуется с возвращением, но квартал попадает в выборку, если он отобран в первый раз). *Следующие 3 файла draw file1.sav draw file2.sav draw file3.sav содержат промежуточные результаты. Их назначение - понять и проверить действия синтаксиса.. * Автор: Raynald Levesque raynald@spsstools.net . *************************************************************. * Для примера сгенерируем файл с 1000 наблюдений. *************************************************************. NEW file. input program. loop block=1 to 1000. leave block. compute pop=RND(uniform(10000)). FORMATS block pop (F8.0). end case. end loop. end file. end input program. execute. SET MPRINT=ON. */////////////////////////// НАЧАЛО МАКРОСА //////////////////////////////. DEFINE !SAMPLE (draw=!TOKENS(1) /keep=!TOKENS(1)) COMPUTE case# =$casenum. CREATE t_weight=CSUM(pop). SORT CASES BY case#(D). CREATE c_weight= CSUM(pop). SORT CASES BY case#. IF $casenum=1 #tot_pop=c_weight. VECTOR rva rvb (!draw F8.0). !DO !cnt = 1 !TO !draw DO IF $casenum=1. COMPUTE !CONCAT(rva,!cnt)=UNIFORM(#tot_pop). LEAVE !CONCAT(rva,!cnt). COMPUTE !CONCAT(rvb,!cnt)=!CONCAT(rva,!cnt)lag(t_weight)). END IF. !DOEND COMPUTE flag=MAX(rvb1 TO !CONCAT('rvb',!draw)). SAVE OUTFILE='draw file1.sav' /COMPRESSED. SELECT IF (flag=1). EXECUTE. SAVE OUTFILE='draw file2.sav' /COMPRESSED. VECTOR rvb=rvb1 TO !CONCAT(rvb,!draw). * Квартал считается отобранным, если в одной из переменных rvb в его строке стоит 1. * Таким образом, один и тот же квартал может быть отобран более 1 раза. Это не значит, что его строка повторяется более 1 раза. Это значит, что в переменных rvb единицы в его строке встречаются более 1 раза - А.Б. *Следующая задача - сохранить лишь первый отбор квартала. COMPUTE done=0. LOOP cnt=1 TO !draw. DO IF rvb(cnt)=1 AND done=0. XSAVE OUTFILE='draw file3.sav' /KEEP block cnt. COMPUTE done=1. END IF. END LOOP. EXECUTE. GET FILE='draw file3.sav'. SORT CASES BY cnt. SELECT IF ($casenum<=!keep). EXECUTE. !ENDDEFINE. */////////////////////////// КОНЕЦ МАКРОСА //////////////////////////////. * Например, нам требуется отобрать 120 кварталов. Сначала мы отбираем 150 кварталов (с возможными повторами), повторяющиеся кварталы отсеиваем. Затем полученные кварталы перемешиваем и отбираем первые 120. !SAMPLE draw=150 keep=120. *Примеч.: при недостаточном числе отборов с повторами требуемого числа keep (без повторов) может и не набраться. Например, если есть множество мелких и несколько крупных кварталов. В таких случаях можно пробовать увеличивать число draw относительно числа keep, причём не обязательно ограничивать draw размером выборки.- А.Б.