파이썬 pandas KeyError 컬럼 오류를 실제 라벨과 인덱스로 확인하는 방법

pandas에서 KeyError: '컬럼명'이나 not in index가 발생하면 먼저 코드가 요청한 라벨과 DataFrame에 실제로 들어 있는 라벨이 같은지 확인해야 합니다. 눈으로 보기에 같은 이름이어도 앞뒤 공백이나 대소문자 차이가 있거나, set_index() 뒤 컬럼이 인덱스로 이동했을 수 있습니다. 운영 중인 자동화라면 결측값 처리나 무시 옵션으로 넘어가기 전에 이 구조부터 확인하는 편이 안전합니다.

KeyError와 not in index는 무엇을 말하나

DataFrame의 컬럼 선택은 위치가 아니라 라벨을 기준으로 동작합니다. 따라서 df['price']는 price라는 라벨을 찾고, df[['date', 'price']]는 요청한 라벨들을 모두 확인합니다. 요청한 라벨이 현재 컬럼 축에 없으면 선택 단계에서 오류가 납니다.

df.columns는 현재 DataFrame의 실제 컬럼 라벨을 pandas.Index로 보여 주는 출발점입니다. 먼저 코드가 기대하는 이름과 실제 값을 나란히 확인합니다.

requested = ['date', 'price']

print('실제 컬럼:', list(df.columns))
print('요청 컬럼:', requested)
print('빠진 컬럼:', [name for name in requested if name not in df.columns])

df['price']에서 보이는 KeyError는 단일 라벨 선택이 실패했다는 뜻이고, 여러 컬럼을 선택하는 코드의 not in index도 요청 목록 중 하나 이상이 현재 축에서 발견되지 않았다는 같은 구조의 문제로 볼 수 있습니다. 이 단계에서 오류를 숨기기보다 빠진 이름을 확인해야 잘못된 열을 대신 사용하는 일을 피할 수 있습니다. 자세한 선택 규칙은 pandas의 인덱싱 및 데이터 선택 문서에서 확인할 수 있습니다.

화면에 같아 보여도 다른 라벨인지 확인하기

컬럼 목록을 출력했는데 이름이 있는 것처럼 보인다면 문자열의 표현을 그대로 확인합니다.

for column in df.columns:
    print(repr(column))

repr()은 눈에 잘 보이지 않는 앞뒤 공백 같은 차이를 드러내는 데 도움이 됩니다. Price와 price처럼 대소문자가 다르거나, 입력 과정에서 컬럼명 끝에 공백이 붙은 경우에도 pandas는 서로 다른 라벨로 취급합니다. BOM이 포함된 입력 라벨처럼 일반 출력에서 알아보기 어려운 문자도 같은 방식으로 먼저 존재 여부를 확인해야 합니다.

정말 모든 입력에서 같은 규칙을 적용하기로 결정했다면 컬럼 라벨을 정규화할 수 있습니다.

df = df.rename(columns=lambda name: name.strip() if isinstance(name, str) else name)

이 코드는 문자열 라벨의 양쪽 공백만 제거합니다. 대소문자 변경이나 특수문자 제거까지 한꺼번에 적용하면 서로 다른 의미의 컬럼을 합칠 수 있으므로, 입력 계약에서 허용한 규칙만 선택적으로 적용해야 합니다. 이름을 특정 라벨로 바꾸려는 상황이라면 rename(columns=...)를 사용하고, 바꾸려는 대상이 실제로 존재해야 한다면 errors='raise' 설정으로 오타를 조기에 드러낼 수 있습니다. pandas의 rename 문서도 함께 확인해 두면 좋습니다.

컬럼이 아니라 인덱스에 있는지 확인하기

set_index()를 거친 뒤 원래 있던 컬럼을 찾지 못한다면, 그 값이 인덱스로 이동했는지 확인합니다.

print('컬럼:', [repr(name) for name in df.columns])
print('인덱스 이름:', [repr(name) for name in df.index.names])
print('인덱스 값 예시:', df.index[:3])

set_index('date')처럼 기존 컬럼을 인덱스로 설정하면 그 라벨은 컬럼 축에서 빠질 수 있습니다. 그래서 이후 df['date']가 실패하는 것은 이름이 바뀐 문제가 아니라 값을 찾는 축이 달라진 문제일 수 있습니다. pandas 문서의 set_index()는 기존 컬럼을 행 인덱스로 설정하는 동작과 drop=True 기본 동작을 설명하고 있습니다.

인덱스를 다시 일반 컬럼으로 사용할 필요가 있고 데이터 흐름상 중복이 괜찮다면 다음처럼 복원할 수 있습니다.

df = df.reset_index()

반대로 날짜나 식별자를 행을 찾는 기준으로 계속 사용할 목적이라면 reset_index()를 무조건 적용하지 말고, 선택 코드를 인덱스 접근에 맞게 바꾸는 편이 낫습니다. set_index() 공식 문서에서 reset_index()와의 관계도 확인할 수 있습니다.

rename()과 reset_index() 중 무엇을 선택할까

두 메서드는 해결하는 문제가 다릅니다.

확인 결과 선택할 조치
라벨은 컬럼 축에 있지만 이름이 오타·공백·표기 차이로 다름 입력 규칙을 확인한 뒤 rename(columns=...) 또는 제한적인 정규화
요청한 라벨이 df.index.names에 있음 컬럼으로 써야 할 때 reset_index(), 인덱스로 쓸 때 선택 코드 수정
두 곳 어디에도 없고 입력 계약상 필수임 원본 입력과 스키마를 확인하고 처리 중단

rename()은 컬럼 라벨의 이름을 바꾸는 작업이지, 인덱스에 있는 값을 컬럼으로 이동하는 작업이 아닙니다. 반대로 reset_index()는 이름 오타를 고치는 도구가 아닙니다. 이 둘을 구분하면 오류를 없애기 위해 데이터를 임의로 덮어쓰는 일을 줄일 수 있습니다.

없는 컬럼을 무시해도 되는가

필수 컬럼이 빠진 경우에는 자동화가 계속 실행되면 안 됩니다. 예를 들어 가격이나 식별자처럼 뒤 계산의 의미를 결정하는 컬럼이 없다면, 다른 컬럼을 대신 연결한 결과가 더 위험할 수 있습니다. 이때는 빠진 라벨과 실제 컬럼 목록을 로그로 남기고 원본 입력을 확인하는 것이 우선입니다.

반면 여러 입력 형식에서 선택적 컬럼이 정말 선택 사항으로 정의되어 있고, 없는 경우의 대체 동작이 명확하다면 조건문으로 분기할 수 있습니다.

optional = 'note'
if optional in df.columns:
    notes = df[optional]
else:
    notes = None

핵심은 오류를 없애는 것이 아니라, 해당 라벨이 없어도 결과의 의미가 유지되는지 먼저 결정하는 것입니다. df.get()처럼 누락을 곧바로 빈 값으로 바꾸는 방식은 이 판단을 대신해 주지 않습니다.

운영 자동화에 넣을 확인 순서

저라면 데이터가 들어온 직후 다음 순서로 확인합니다.

  1. repr()로 df.columns의 실제 라벨을 확인합니다.
  2. 요청한 라벨과 실제 컬럼 라벨의 차이를 분리합니다.
  3. 요청한 이름이 df.index.names에 있는지 확인합니다.
  4. 이름 표기 문제라면 제한적인 rename()을 적용하고, 인덱스 문제라면 reset_index() 필요성을 판단합니다.
  5. 필수 라벨이 없으면 처리를 중단하고 입력 스키마를 수정합니다.

이 순서를 코드에 남겨 두면 다음 입력에서 같은 문제가 생겼을 때 원인을 재현하기 쉬워집니다. 특히 컬럼 정규화는 입력 계약을 정한 뒤 적용하고, 실제 데이터의 의미가 달라질 수 있는 대소문자 변경이나 무조건적인 컬럼 삭제는 피하는 것이 좋습니다.

마무리

pandas KeyError의 첫 확인 지점은 예외 문구 자체가 아니라 현재 DataFrame의 라벨 구조입니다. df.columns와 repr()로 보이지 않는 차이를 확인하고, df.index.names로 인덱스 이동을 구분한 다음, rename()과 reset_index() 중 원인에 맞는 조치를 선택하면 됩니다. 필수 컬럼이 없을 때는 오류를 숨기지 말고 입력을 멈추는 것이 데이터 품질을 지키는 방법입니다.

참고 자료: pandas.DataFrame.columns, Indexing and selecting data, pandas.DataFrame.set_index, pandas.DataFrame.rename

Leave a Comment