데이터 수집 및 적재 파이프라인에서 발생하는 시스템 오류, 로그 누적 또는 여러 웹 페이지에서의 중복 크롤링 등으로 인해 동일한 정보가 여러 번 기록된 ‘중복 데이터(Duplicate Data)’를 마주하게 됩니다. 데이터 가공의 핵심은 이러한 불필요한 행들을 적절히 필터링하고 분석 대상의 고유성(Uniqueness)을 확보하는 것입니다.
중복된 상태의 데이터를 그대로 분석 모델의 훈련에 활용하거나 통계적 수치 도출에 사용하면 특정 데이터 패턴이 과도하게 반영되어 모델 성능 평가가 왜곡될 수 있습니다. 파이썬(Python) 판다스(Pandas) 라이브러리는 이를 해결하기 위해 중복 검사용 duplicated()와 제거용 drop_duplicates() 함수를 제공합니다. 이번 글에서는 두 함수의 상세한 사용법과 비즈니스 활용 사례, 그리고 데이터 정제 시 유의해야 할 예외 제어 방안을 정리하겠습니다.
1. 데이터셋 내 중복 값 진단하기: duplicated() 함수
중복 데이터를 삭제하기 전에 어떤 행들이 중복되어 있는지 먼저 확인하는 것이 안전합니다. 판다스에서는 duplicated() 함수를 사용하여 각 행의 중복 여부를 불리언(True/False) 시리즈로 반환받을 수 있습니다.
1.1. duplicated()의 핵심 원리
duplicated() 함수는 데이터프레임의 첫 행부터 아래로 내려가며 이전 행들과 완전히 동일한 데이터가 재등장하는 경우 해당 행을 True로 마킹합니다.
import pandas as pd
# 가상의 비즈니스 마케팅 수신 고객 데이터 생성
marketing_df = pd.DataFrame({
'고객ID': ['C001', 'C002', 'C001', 'C003', 'C002'],
'이름': ['김민수', '이영희', '김민수', '박준영', '이영희'],
'가입채널': ['웹', '모바일', '웹', '모바일', '웹']
})
# 전체 데이터프레임 기준 중복 여부 판정
print(marketing_df.duplicated())
[출력 결과]
0 False
1 False
2 True
3 False
4 False
dtype: bool
인덱스 2번 행의 경우, 인덱스 0번 행과 ‘고객ID’, ‘이름’, ‘가입채널’ 값이 모두 완벽히 일치하기 때문에 중복(True)으로 판정되었습니다. 반면 인덱스 4번 행은 ‘고객ID’와 ‘이름’은 인덱스 1번 행과 같지만 ‘가입채널’이 다르므로 중복으로 간주되지 않았습니다.
1.2. 중복 행의 총 개수 파악하기
분석 대상 데이터프레임이 거대할 때는 아래와 같이 sum() 함수를 결합해 전체 중복 샘플이 몇 개 존재하는지 간결하게 파악할 수 있습니다.
# 전체 중복 데이터의 빈도수 계산
duplicate_count = marketing_df.duplicated().sum()
print(f"중복된 행의 총 개수: {duplicate_count}")
2. 중복 데이터 정교하게 지우기: drop_duplicates() 함수
중복의 규모를 파악한 후에는 drop_duplicates()를 사용해 중복 행을 제거합니다. 이 함수는 데이터 분석 실무에서 가장 활용도가 높은 클렌징 함수 중 하나입니다.
2.1. 주요 파라미터 상세 분석
- subset: 중복을 판정할 기준 컬럼을 리스트 형태로 지정합니다. 생략하면 데이터프레임 전체 열의 값이 모두 일치하는 행을 기준으로 삼습니다.
- keep: 중복된 행 중 어떤 것을 남길지 결정합니다.
'first': 가장 먼저 등장한 행을 유지하고 이후의 중복들을 삭제합니다. (기본값)'last': 가장 마지막에 등장한 중복 행을 유지하고 이전 행들을 삭제합니다.False: 중복 그룹에 포함된 모든 행을 제거하고, 유일하게 존재하는 행만 유지합니다.
- ignore_index:
True로 설정하면 정제 후 분산된 기존 인덱스를 0부터 시작하는 순차적인 정수로 다시 정렬합니다. (기본값은False)
2.2. 비즈니스 예시로 보는 중복 데이터 정제
[사례 A] 모든 열이 완벽히 일치하는 중복 행 제거
# 첫 번째 행을 남기고 나머지 완전 중복 행 제거 및 인덱스 정돈
clean_all = marketing_df.drop_duplicates(ignore_index=True)
[사례 B] 특정 핵심 열을 기준으로 중복 필터링하기
실무에서는 고객ID처럼 업무적으로 동일 대상을 식별하는 키 컬럼을 기준으로 중복 데이터를 제거해야 하는 경우가 있습니다. 이때 subset 파라미터를 활용합니다.
# '고객ID'를 기준으로 중복을 판정하되, 가장 최근에 인입된 마지막(last) 행을 유지
clean_customer = marketing_df.drop_duplicates(subset=['고객ID'], keep='last', ignore_index=True)
print(clean_customer)
[출력 결과]
| 고객ID | 이름 | 가입채널 | |
| 0 | C001 | 김민수 | 웹 |
| 1 | C003 | 박준영 | 모바일 |
| 2 | C002 | 이영희 | 웹 |
keep='last' 설정에 따라 인덱스 1번 행 대신 가장 나중에 입력된 인덱스 4번 행(‘가입채널’: ‘웹’)의 데이터가 최종적으로 반영되었음을 확인할 수 있습니다.
3. 데이터 품질 관리를 위한 실무 정제 팁 및 유의사항
3.1. 시계열 데이터와 결합된 최신 값 유지 전략
비즈니스 원본 테이블에 수집 시간이 기록되는 ‘Timestamp’나 ‘수정일자’ 컬럼이 포함된 경우가 많습니다. 이러한 환경에서는 sort_values()를 사용하여 시간 역순(최신순)으로 데이터를 정렬한 뒤 drop_duplicates()를 실행하면, 자연스럽게 해당 시점 기준의 최신 이력 데이터만 보존하는 데이터 동기화 파이프라인을 구축할 수 있습니다.
# 가상 거래 이력 데이터 (시간 순서대로 혼재)
transaction_df = pd.DataFrame({
'계좌번호': ['A101', 'A101', 'B201', 'A101'],
'거래금액': [5000, 12000, 45000, 3000],
'거래시간': ['10:00', '10:15', '11:00', '10:05']
})
# 1. 거래시간 기준 내림차순(최신순) 정렬
sorted_tx = transaction_df.sort_values(by='거래시간', ascending=False)
# 2. 계좌번호 기준으로 가장 최근(첫 번째) 이력만 보존
latest_tx = sorted_tx.drop_duplicates(subset=['계좌번호'], keep='first', ignore_index=True)
3.2. 대용량 데이터셋 가공 시 메모리 효율 관리
inplace=True 설정은 원본 데이터프레임을 직접 변경하는 방식으로 사용할 수 있지만, 항상 메모리 사용량 감소를 보장하는 것은 아닙니다. 또한 코드 재사용성과 디버깅 측면에서는 대입 방식(df = df.drop_duplicates(…))이 더 명확할 수 있습니다.
수백만 건의 대규모 트랜잭션 로그를 정제하는 환경이 아니라면, 가급적 대입 연산자(df = df.drop_duplicates(...))를 활용하거나 명시적인 .copy() 호출을 적용하는 것이 예기치 않은 메모리 에러를 예방하는 합리적인 대안이 됩니다.
4. 빅데이터분석기사 실기 시험 환경에서의 실전 활용 포인트
빅데이터분석기사 실기(특히 작업형 제1유형)에서는 특정 조건으로 중복 데이터를 제거한 뒤, 남은 관측치들의 통계 값을 구하라는 유형이 지속적으로 출제됩니다.
4.1. 중복 제거 전후의 샘플 수 비교 및 연산
예를 들어 “고객 정보 테이블에서 고객ID 기준 중복을 모두 제거한 후의 데이터셋 평균 구매액과, 중복을 제거하기 전의 평균 구매액 차이의 절댓값을 구하시오”라는 문제가 있다면 아래와 같은 순서로 코드를 간결하게 작성할 수 있습니다.
# 1. 원본 데이터프레임의 구매액 평균 계산
original_mean = df['구매액'].mean()
# 2. 고객ID 기준 중복 제거 적용 (첫 행 유지)
deduplicated_df = df.drop_duplicates(subset=['고객ID'], keep='first')
# 3. 중복 제거 후 구매액 평균 계산
new_mean = deduplicated_df['구매액'].mean()
# 4. 차이의 절댓값 계산
result = abs(original_mean - new_mean)
print(result)
이와 같이 중복 데이터 제거 기술은 데이터의 유일성을 확보하여 데이터 모델링에 가해지는 통계적 착시를 해소하고 신뢰성 높은 결과물을 얻는 기초가 됩니다.
5. 요약 및 다음 화 안내
duplicated():데이터프레임 내 중복 행을 True로 판정하여 중복 데이터 존재 여부와 개수를 확인하도록 지원합니다.drop_duplicates(): 지정한 컬럼 기준(subset)에 따라 중복 행들을 걸러내며,keep옵션을 사용하여 데이터 보존 정책(처음 값 혹은 마지막 값)을 커스터마이징할 수 있습니다.- 인덱스 정리: 중복 행이 빠져나가면서 생기는 중간 인덱스의 유실을 방지하기 위해
ignore_index=True옵션을 병행하여 연산 가독성을 높입니다.
다음 [판다스 13화]에서는 텍스트 형식으로 입수된 범주형 정보에서 핵심 키워드를 추출하고 정제하기 위해 필수적인 문자열 데이터 처리(str 함수) 실무 활용법에 대해 상세하게 알아보겠습니다. 문자열 슬라이싱과 패턴 정합성을 분석하는 파이썬 판다스의 텍스트 조작 기술을 함께 습득해 봅시다.