Сложный безповторный отбор
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 | SPSS AnswerNet Код решения: 100000760 ПО: SPSS Base Версия: ОС: Тип вопроса: Синтакс/пакетный режим/Скрипты Подтип вопроса: Преобразования данных Заголовок: Сложная выборка "с близнецами" без возвращения. Описание: Вопрос. В файле данных есть записи о трёх типах испытуемых. Первый тип представляет для меня особый интерес в моём исследовании. Второй испытуемых - это члены семьи первых. Третий тип - люди, которые не связаны родственными отношениями с первыми двумя типами. Мне требуется сопоставить записи первого типа с записями первых двух типов так, чтобы они подходили друг другу по полу и возрасту. При этом нужно гарантировать, что ни в какой паре не окажутся люди из одной и той же семьи. А кроме того - что ни один человек не попадёт в выборку дважды. Просто не знаю, в каком направлении начать поиски. Ответ. Задача нетривиальная, но способ есть. Идея решения - для начала сопоставить каждому ID человека все ID других людей, которые подходят по комбинации пол/возраст. Затем пары ID из таких перечней случайным образом отбираются в выборку, после чего соответствующие ID исключаются из рассмотрения. Найденные пары записываются в файл 'YOKED.SAV'. Те, для кого пары не нашлось, записываются в файл 'UNPAIRED.SAV'. Следующая программа может быть изменена таким образом, чтобы допускать более, чем 20 записей в каждой различимой комбинации пол/возраст. data list FREE/ FAMILY AGE GENDER Z PRIMARY. BEGIN DATA 1 1 1 2 1 1 2 1 4 2 2 3 2 2 1 2 4 2 3 2 3 3 2 3 1 3 2 1 2 2 4 4 2 3 1 4 3 2 1 2 5 1 1 3 1 5 2 2 2 2 6 3 1 2 1 6 4 1 2 2 7 2 2 2 1 7 3 2 1 2 8 2 1 2 1 8 3 2 1 2 9 1 1 1 1 9 2 2 3 2 10 3 2 9 1 10 2 1 1 2 11 2 1 2 1 11 2 1 2 2 12 3 1 2 1 12 3 2 1 2 13 1 1 3 1 14 2 2 1 1 15 1 2 2 1 16 2 1 5 1 17 4 2 2 1 18 3 2 1 1 19 4 1 5 1 20 4 1 1 1 21 1 2 5 1 22 3 2 4 1 23 4 1 5 1 24 2 2 8 1 25 4 1 2 1 26 3 2 1 1 27 2 1 5 1 28 4 1 1 1 29 3 2 3 1 30 2 2 6 1 31 4 1 4 1 32 3 1 2 1 33 1 2 2 1 34 3 1 1 1 35 4 2 1 1 36 2 1 4 1 END DATA . COMPUTE OLDSEQ=$CASENUM. SAVE OUTFILE 'RAWDATA.SAV' . * Сделаем так, чтобы записи первого типа содержали информацию об объекте второго типа из той же семьи *. * Создадим для этого дополнительную переменную *. SORT CASES BY FAMILY (A) PRIMARY (D). IF FAMILY=LAG(FAMILY) TWIN=LAG(OLDSEQ). * Пересчитаем все записи внутри каждой страты ВОЗРАСТ/ПОЛ (AGE/GENDER) *. SORT CASES BY AGE GENDER . IF (MISSING(LAG(OLDSEQ))) STCNT=1. IF (AGE=LAG(AGE) AND GENDER=LAG(GENDER)) STCNT=LAG(STCNT) +1. IF (MISSING(STCNT)) STCNT=1. * Распределим информацию об ID-номерах всех кандидатов на "спаривание" по всем наблюдениям в пределах категории пол/возраст *. * Оставим только записи первого типа *. VECTOR ID_(20). COMPUTE ID_(STCNT)=OLDSEQ. AGGREGATE OUTFILE 'C:\\TEMP\\TMP.SAV' / PRESORTED/ BREAK=AGE GENDER / TWIN=FIRST(TWIN) / ID_X01 TO ID_X20 = MAX(ID_1 TO ID_20). SELECT IF PRIMARY=1. MATCH FILES FILE=* / TABLE='C:\\TEMP\\TMP.SAV' / BY AGE GENDER. * Проверяем, находится ли текущая запись в той же страте, что и предыдущая *. * Если так, эта запись "наследует" перечень ID-номеров кандидатов на "спаривание" *. * (IMHO, проверка и копирование лишние - предыдущая команда MATCH FILES уже размножила нужные ID - А.Б.) COUNT MAXVALID=ID_X01 TO ID_X20 (LO THRU HI). DO IF AGE=LAG(AGE) AND GENDER=LAG(GENDER) . + DO REPEAT ID=ID_X01 TO ID_X20 . + COMPUTE ID = LAG(ID) . + END REPEAT. END IF. * Зададим вектор с ID возможных кандидатов *. VECTOR ID_X=ID_X01 TO ID_X20 . * Важно не сопоставить запись самой себе! *. DO IF NOT MISSING (ID_X(STCNT) ). * Обнулим флаги состояния *. + DO REPEAT INIT=TAKEN FOUND NTRYS . + COMPUTE INIT=0. + END REPEAT. * Ведём случайный отбор пар ID в векторе, копируем в YOKE и уничтожаем оригинал *. + LOOP. + COMPUTE WHICH=TRUNC(UNIFORM(MAXVALID))+1. + IF WHICH <> STCNT YOKE=ID_X(WHICH). + DO IF (NOT (ANY(YOKE,TWIN,OLDSEQ,$SYSMIS))) . + COMPUTE ID_X(WHICH)=$SYSMIS . + COMPUTE ID_X(STCNT)=$SYSMIS . + COMPUTE FOUND=1. + END IF . + END LOOP IF FOUND. ELSE. COMPUTE TAKEN=1. END IF. * Разделим все записи на нашедшие пару и ненашедшие. Оставим информацию об их ID * . TEMPORARY . SELECT IF (MISSING (YOKE) AND NOT(TAKEN) ). SAVE OUTFILE 'UNPAIRED.SAV' . SELECT IF (NOT (TAKEN) AND NOT MISSING (YOKE) ). SAVE OUTFILE 'TMP' / KEEP OLDSEQ YOKE. GET FILE 'TMP'. COMPUTE GROUP=$CASENUM . * Преобразуем пары из одной записи в пары записей *. VECTOR V = OLDSEQ TO YOKE . LOOP X=1 TO 2. COMPUTE OLDSEQ=V(X). XSAVE OUTFILE 'TMP2' / KEEP GROUP X OLDSEQ . END LOOP. EXECUTE. * Добавим к полученным ID исходные данные, не участвовавшие в отборе * В ДАННОМ СЛУЧАЕ - ПЕРЕМЕННАЯ Z * . GET FILE 'TMP2'. SORT CASES BY OLDSEQ. MATCH FILES FILE = * / TABLE = 'RAWDATA.SAV' / BY OLDSEQ . SORT CASES BY GROUP. ******************************************************** . * Распространим значения данных на пары записей: * . * вам потребуется сделать обобщение этой процедуры на несколько переменных * . * КАК-ТО ТАК... * . * VECTOR ID(2). * . * DO REPEAT VAR = Y Z . * . * VECTOR VAR(2) . * . * COMPUTE VAR(X) = VAR . * . * END REPEAT . * . * AGGREGATE ...../ Y1 Y2 Z1 Z2 = MAX(Y1 Y2 Z1 Z2).* . ******************************************************** . VECTOR Z(2) / ID(2). COMPUTE Z(X) = Z. COMPUTE ID(X)=OLDSEQ. AGGREGATE OUTFILE * / PRESORTED / BREAK=GROUP GENDER AGE / Z1 TO Z2 = MAX(Z1 TO Z2) / ID1 TO ID2 = MAX(ID1 TO ID2). SAVE OUTFILE 'YOKED.SAV'. LIST. * Результаты! * . GROUP GENDERAGE Z1 Z2 ID1 ID2 1 1 1 2 3 1 9 2 1 1 1 3 17 25 3 2 1 2 5 27 33 4 1 2 2 4 15 48 5 1 2 2 1 21 20 6 1 2 5 4 28 2 7 1 2 5 2 39 6 8 2 2 2 2 13 10 9 2 2 1 3 26 18 10 2 2 8 6 36 42 11 1 3 2 2 11 23 12 1 3 2 1 44 46 13 2 3 2 3 3 5 14 2 3 9 3 19 41 15 2 3 1 1 30 8 16 2 3 4 1 34 38 17 1 4 5 2 31 12 18 1 4 1 5 32 35 19 1 4 2 1 37 40 20 2 4 3 1 7 47 21 2 4 2 3 29 4 Number of cases read: 21 Number of cases listed: 21 |
Related pages
...