Самый простой способ создания уникальных транзитивных идентификаторов на основе существующих идентификаторов - PullRequest
1 голос
/ 20 апреля 2019

Предположим, у меня есть набор данных, который выглядит следующим образом:

obs id1 id2
1   a   1
2   b   2
3   c   2
4   d   3
5   e   4
6   b   5
7   f   6

Я хочу создать уникальную транзитивную id переменную для этого набора данных.И id1, и id2 используются для идентификации лиц.Так что, если у индивидуума X есть то же id1, что и у индивидуума Y или , то же самое id2, что и у индивидуума Y, тогда X=Y.

Итак, в этомНапример, предполагаемый результат будет выглядеть следующим образом:

obs id1 id2 uniqid
1   a   1   1
2   b   2   2
3   c   2   2
4   d   3   3
5   e   4   4
6   b   5   2
7   f   6   5

Здесь наблюдение 6 имеет id1 "b", которому уже присвоен uniqid 2 (по наблюдению 2), иИтак, наблюдение 6 идентифицирует того же человека, что и наблюдение 2.

Теперь, сравнивая наблюдения 3 и 6, мы видим, что эти наблюдения не разделяют ни id1, ни id2, но все же идентифицируют одного и того же человека, поскольку оба они идентифицируют одного и того же человека как наблюдение 2.

В настоящее время я работаю в Stata, и мне было интересно, как лучше всего это сделать.Я бы предпочел решение на основе Stata, но мне также было бы интересно посмотреть на решения R или Python.

Ответы [ 2 ]

2 голосов
/ 21 апреля 2019
  1. Предоставленный сообществом group_twoway (доступен в SSC) - это прямое решение вашей проблемы. Вы должны убедиться, что id1 и id2 имеют одинаковый тип (числовой или строковый) и что в их диапазоне нет перекрывающихся значений. Ниже код работает для вашего примера.

    ssc install group_twoway

    gen id2_str = string(id2)
    group_twoway id1 id2_str, gen(id)
    
  2. Еще один шаг, добавленный к решению Pearly (с group_id), сделает его подходящим для вашей проблемы без ручной настройки.

    clonevar x = id1 
    group_id x, match(id2)
    
    egen id = group(x)
    
  3. Если вам кажется, что эти пакеты слишком «черные ящики», то нижеприведенный код - это ... язык кодирования для вашего логического желания.

    egen x0 = group(id1)
    egen x1 = min(x0), by(id2)
    
    local i=1
    while r(N) <_N {
    egen x`=`i'+1' = min(x`i'), by(x`=`i'-1')
    count if x`i++' == x`i'
    }
    
    egen id = group(x`i')
    drop x*
    
2 голосов
/ 21 апреля 2019

Команда , предоставленная сообществом Команда Stata group_id делает то, что вы хотите.

Однако, это оставляет несопоставленные идентификаторы неизменными:

clear
input obs str1 id1 id2
1   a   1
2   b   2
3   c   2
4   d   3
5   e   4
6   b   5
7   f   6
end

clonevar id = id2 
group_id id, match(id1)
sort obs 

list, separator(0)

     +----------------------+
     | obs   id1   id2   id |
     |----------------------|
  1. |   1     a     1    1 |
  2. |   2     b     2    2 |
  3. |   3     c     2    2 |
  4. |   4     d     3    3 |
  5. |   5     e     4    4 |
  6. |   6     b     5    2 |
  7. |   7     f     6    6 |
     +----------------------+

Вот еще один пример того, что это действительно так:

clear
input obs str1 id1 id2
1   a   1
2   b   2
3   c   7
4   d   3
5   e   4
6   b   5
7   f   1
end

clonevar id = id2 
group_id id, match(id1)
sort obs

list, separator(0)

     +----------------------+
     | obs   id1   id2   id |
     |----------------------|
  1. |   1     a     1    1 |
  2. |   2     b     2    2 |
  3. |   3     c     7    7 |
  4. |   4     d     3    3 |
  5. |   5     e     4    4 |
  6. |   6     b     5    2 |
  7. |   7     f     1    1 |
     +----------------------+

Если вы хотите иметь непрерывные идентификаторы после совпадения (то есть 5 вместо 6 в первом примере и 7 во втором), вам придется настроить их вручную.

...