CSV 도우미English

CSV 중복 제거: 행 전체와 코드 한 열은 결과가 다릅니다

같은 코드가 두 번 나온다고 같은 데이터인 것은 아닙니다. 수량이 다른 주문을 코드만으로 중복 제거하면 필요한 기록까지 사라질 수 있습니다. 삭제 전에 비교할 열과 남길 행의 기준부터 정하세요.

원인

중복은 비교 기준에 따라 달라집니다. ‘행 전체가 같은가’와 ‘코드만 같은가’는 다른 질문입니다. 앞뒤 공백과 대소문자를 무시할지에 따라서도 결과가 바뀝니다. 이 글에서는 각 기준에서 처음 나타난 행을 남기는 규칙을 사용합니다. 최신 행을 찾거나 수량을 합치는 규칙은 아닙니다.

Microsoft도 중복 삭제 전 원본 복사를 권하며 비교할 열을 선택하도록 안내합니다. 아래 검증은 Excel의 화면·비교 알고리즘을 재현한 것이 아니라, 명시한 규칙을 Python으로 실행한 결과입니다. Microsoft 공식 안내

재현

05-duplicates.csv는 헤더와 데이터 6개입니다. 다섯 번째 데이터의 코드 앞에는 공백 하나가 있습니다.

code,item,qty
A01,pen,1
A01,pen,1
A01,pen,2
A02,note,1
 A02,note,1
a02,note,1

다음 코드를 예제와 같은 폴더에서 실행하세요. CSV reader로 문자열을 읽으며 숫자·날짜로 변환하지 않습니다. Python csv 문서

import csv
with open('05-duplicates.csv', encoding='utf-8', newline='') as f:
    rows = list(csv.reader(f, strict=True))

def keep_first(rows, columns=None, normalize=False):
    seen, kept = set(), [rows[0]]
    for row in rows[1:]:
        values = row if columns is None else [row[i] for i in columns]
        key = tuple(v.strip().lower() if normalize else v for v in values)
        if key not in seen:
            seen.add(key)
            kept.append(row)
    return kept

full = keep_first(rows)
code = keep_first(rows, [0])
normalized = keep_first(rows, [0], normalize=True)
print(len(full) - 1, len(code) - 1, len(normalized) - 1)

실행 결과는 5 4 2입니다.

이 예제의 공백·대소문자가 실제로 같은 식별자를 뜻하는지는 데이터 소유자의 규칙으로 결정해야 합니다. 적게 남는 결과가 더 정확한 결과라는 뜻은 아닙니다.

해결

원본을 보관한 상태에서 먼저 비교 기준을 확인합니다. 전송 과정에서 완전히 같은 행이 반복된 문제라면 행 전체 비교부터 검토합니다. 같은 코드의 여러 기록을 하나로 만들 필요가 있다면 어떤 날짜·수량을 남길지 별도로 결정합니다. 이 글의 코드 한 열 예시는 손실 가능성을 보여주는 비교용이며 권장 정리 결과가 아닙니다.

합의한 기준으로 만든 새 사본을 재파싱해 헤더·남은 행·삭제된 행을 대조합니다. 아래는 행 전체 기준 결과를 저장하는 예제입니다.

with open('05-full-row.csv', 'w', encoding='utf-8', newline='') as f:
    csv.writer(f, lineterminator='\r\n').writerows(full)
with open('05-full-row.csv', encoding='utf-8', newline='') as f:
    assert list(csv.reader(f, strict=True)) == full

출력 예제는 행 전체 기준, 코드만 기준, 코드 공백·대소문자 무시 기준입니다. 세 사본 모두 저장 후 다시 읽은 값이 계산 결과와 같고, 처리 중 입력 원본이 바뀌지 않았음을 확인했습니다. 정규화는 비교 키에만 적용하며 남기는 행의 셀 값을 다시 쓰지 않는 규칙입니다.

CSV 도우미에서 연결할 도구

**‘중복 행 제거’(/dedupe/)**와 연결합니다. 예제를 선택하고 헤더 있음을 유지합니다. ‘기준 열’을 고르지 않으면 행 전체, code만 고르면 코드 기준입니다. 처음에는 ‘앞뒤 공백 무시’와 ‘대소문자 무시’를 모두 끈 채 결과를 확인하고, 업무 규칙상 같은 값일 때만 옵션을 켜세요.

예제의 기대 결과는 차례로 데이터 유지 5개/삭제 1개, 유지 4개/삭제 2개, 두 옵션을 켜면 유지 2개/삭제 4개입니다. 삭제 후보와 남은 값을 확인한 뒤 새 파일을 내려받는 흐름입니다. 구조가 불분명하거나 열 수가 맞지 않는 파일은 **CSV 검사기(/csv-check/)에서 먼저 확인**합니다.

한계

빈 코드·열 누락·깨진 인용 문법이 있는 파일은 이 예제의 전제와 다릅니다. 빈 코드를 모두 같은 대상으로 묶을지부터 별도로 판단해야 합니다. Python의 strip().lower()와 브라우저 문자열 처리의 세부 규칙은 모든 유니코드 문자에서 동일하다고 보장하지 않습니다. 여기서는 ASCII 코드와 일반 공백만 검증했습니다.

검토일: 2026-10-18. Python 3.9.6에서 기준별 유지/삭제 수·첫 행 유지·헤더 보존·수량이 다른 행의 손실·출력 재파싱을 검증했습니다. Excel GUI는 필요하지 않으며 실행하지 않았습니다. 사이트 도구의 옵션·비교 방식은 현재 소스를 확인했으나 이번 작업에서 브라우저 UI 검증은 수행하지 않았습니다.

AI 보조 작성: AI로 초안과 합성 데이터를 작성하고 코드 실행으로 결과를 확인했습니다. 실제 주문·고객 자료는 사용하지 않았습니다.

이 글의 예제 파일을 CSV 검사기에 넣어 직접 확인해 보세요.

중복 행 제거 열기 ›