Python으로 데이터를 처리하다 보면 리스트나 딕셔너리의 각 요소를 고유하게 식별해야 하는 경우가 자주 발생합니다. 이때 각 요소에 고유한 ID를 부여하게 되는데, 문제는 동일한 값이 여러 번 반복될 때입니다. 반복되는 값에는 매번 새로운 ID가 아니라 동일한 ID가 할당되어야 합니다. 이 글에서는 Python에서 중복 값을 하나의 고유 ID로 묶어 할당하는 두 가지 방법을 소개합니다.
방법 1: enumerate()와 OrderedDict.fromkeys() 조합
enumerate() 함수는 시퀀스에 카운터(인덱스)를 붙여주는 함수입니다. 먼저 OrderedDict.fromkeys()로 리스트에서 순서를 유지한 채 중복을 제거한 뒤, 각 고유 값에 인덱스를 매기고, 원래 리스트의 각 요소에 해당 인덱스(ID)를 대응시키는 방식입니다.
예제 코드
from collections import OrderedDict
Alist = ['Mon','Tue','Wed','Mon',5,3,3]
print("The given list : ",Alist)
# 값에 ID 할당
list_ids = [{v: k for k, v in enumerate(
OrderedDict.fromkeys(Alist))}
[n] for n in Alist]
# 결과 출력
print("The list of ids : ",list_ids)실행 결과
The given list : ['Mon', 'Tue', 'Wed', 'Mon', 5, 3, 3] The list of ids : [0, 1, 2, 0, 3, 4, 4]
출력 결과를 보면 'Mon'은 처음 등장했을 때 0이라는 ID를 받았고, 네 번째 위치에 다시 등장했을 때도 같은 0을 받은 것을 확인할 수 있습니다. 마찬가지로 숫자 3도 두 번 모두 4라는 동일한 ID를 가집니다.
방법 2: collections의 defaultdict 활용
두 번째 방법은 defaultdict를 사용하는 것입니다. defaultdict(lambda: len(d_dict))처럼 기본값 생성 함수를 지정하면, 새로운 키가 처음 접근될 때만 현재 딕셔너리의 길이(즉, 새로운 순번)가 값으로 자동 할당됩니다. 이미 존재하는 키에 다시 접근하면 기존에 저장된 ID가 그대로 반환되므로, 중복 값은 자연스럽게 같은 ID를 공유하게 됩니다.
예제 코드
from collections import defaultdict
# 주어진 리스트
Alist = ['Mon','Tue','Wed','Mon',5,3,3]
print("The given list : ",Alist)
# 값에 ID 할당
d_dict = defaultdict(lambda: len(d_dict))
list_ids = [d_dict[n] for n in Alist]
# ID 목록 출력
print("The list of ids : ", list_ids)실행 결과
The given list : ['Mon', 'Tue', 'Wed', 'Mon', 5, 3, 3] The list of ids : [0, 1, 2, 0, 3, 4, 4]
정리
두 방법 모두 동일한 결과를 내지만 성격이 조금 다릅니다. 첫 번째 방법은 중복 제거와 ID 매핑 과정이 명확히 드러나 가독성이 좋고, 두 번째 방법은 defaultdict의 특성을 활용해 코드가 더 짧고 간결합니다. 참고로 Python 3.7 이상에서는 일반 dict도 삽입 순서를 유지하므로, 첫 번째 방식에서 OrderedDict 대신 일반 딕셔너리를 사용해도 동작합니다. 데이터 전처리나 범주형 데이터에 정수 레이블(label encoding)을 부여할 때 이런 기법을 유용하게 활용할 수 있습니다.