파이썬 pandas KeyError 컬럼 오류, 실제 열 이름과 인덱스 확인 순서

pandas에서 컬럼이 있는 것처럼 보이는데 KeyError가 발생하면 먼저 화면이 아니라 현재 DataFrame의 실제 columns와 index label을 확인해야 합니다. 그다음 입력 파일이 여러 열로 제대로 읽혔는지, 열 이름에 공백이나 개행이 붙었는지, loc과 iloc 중 어떤 접근이 문제의 의도에 맞는지 순서대로 나누어 보시면 됩니다. 이 순서를 지키면 컬럼명 문제와 행 인덱스 접근 문제를 한꺼번에 고치려는 실수를 줄일 수 있습니다.

먼저 오류가 난 대상을 실제 label로 확인하기

print(df)는 값과 표 모양을 보여 주지만, 사람이 읽기 편하게 표시되면서 열 이름의 미세한 공백을 놓칠 수 있습니다. 오류가 난 직후에는 아래처럼 구조를 별도로 확인해 보십시오.

print(df.columns.tolist())
print([repr(column) for column in df.columns])
print(df.index.tolist())

df['고객ID']가 실패했다면 df.columns.tolist()에 정말 고객ID가 있는지 확인합니다. repr 결과에 '고객ID ' 또는 '고객ID\\n'처럼 보이지 않는 문자가 드러나면 코드의 철자보다 원본 열 이름과 입력 정리 방식을 먼저 판단해야 합니다.

공백이 보인다고 항상 무조건 strip()으로 바꾸는 것은 안전하지 않습니다. 그 공백이 원본 데이터에서 의미 있는 구분인지, 파일을 읽는 과정에서 생긴 것인지 확인한 뒤 명시적으로 열 이름을 정리하는 편이 좋습니다.

CSV가 한 열로 읽혔는지 확인하기

자동화에서 자주 만나는 경우는 파일에는 여러 필드가 있는데 DataFrame에는 열이 하나만 생긴 상황입니다. df.columns.tolist()의 결과가 기대한 열 목록이 아니라 구분자를 포함한 긴 문자열 하나라면, 컬럼명을 고치는 문제가 아니라 읽기 단계부터 확인해야 합니다.

read_csv의 sep 또는 delimiter가 필드 구분 방식을 결정하므로 실제 파일의 구분자와 읽기 옵션이 맞아야 합니다. 파일이 세미콜론이나 탭으로 구분되어 있는데 쉼표로 읽으면 의도한 열로 나뉘지 않을 수 있습니다.

import pandas as pd

# 실제 파일 형식에 맞는 구분자를 지정합니다.
df = pd.read_csv("input.csv", sep=";")
print(df.columns.tolist())

header나 index_col 설정도 열 이름과 행 인덱스의 구성에 영향을 줍니다. 따라서 CSV를 다시 읽을 때는 파일의 첫 줄이 헤더인지, 어떤 열을 인덱스로 사용할지까지 입력 계약과 함께 확인해야 합니다. 자동 탐지에 기대기보다 파일 형식을 알고 있다면 sep를 명시하는 편이 운영에서 추적하기 쉽습니다.

컬럼과 인덱스를 혼동하지 않기

set_index("고객ID")를 호출하면 기존 컬럼을 행 인덱스로 설정합니다. drop=True가 기본값이므로 인덱스로 사용한 열은 기본적으로 컬럼에서 제거됩니다. 이후 df['고객ID']가 실패한다면 컬럼이 갑자기 사라진 것이 아니라 행 인덱스로 이동했는지 확인할 수 있습니다.

df = df.set_index("고객ID")

print(df.columns.tolist())
print(df.index.tolist())

# 고객ID가 현재 인덱스 label인 경우
row = df.loc["A001"]

다시 일반 컬럼으로 돌려야 한다면 reset_index()를 고려하되, 이미 같은 이름의 컬럼이 있는지 먼저 살펴야 합니다. 이 글의 핵심은 메서드를 무조건 적용하는 것이 아니라, 오류가 난 키가 현재 컬럼에 필요한지 인덱스에 필요한지를 먼저 결정하는 데 있습니다.

loc과 iloc을 목적에 맞게 선택하기

loc은 label을 기준으로 하므로 현재 인덱스에 "A001"이 없으면 KeyError가 발생할 수 있습니다. 반대로 iloc은 정수 위치를 기준으로 하며 범위를 벗어나면 IndexError가 발생합니다.

# 현재 index에 A001이라는 label이 있을 때
customer = df.loc["A001"]

# 순서상 첫 번째 행이 필요할 때
first_row = df.iloc[0]

loc[5]에서 숫자 5를 썼다고 해서 다섯 번째 행을 의미하는 것도 아닙니다. 인덱스 label이 정수 5인지 찾는 표현입니다. 따라서 “첫 번째 행”이 필요하면 df.iloc[0]처럼 위치를 쓰고, “고객 ID가 A001인 행”이 필요하면 df.loc["A001"]처럼 label을 써야 합니다.

실무 코드에서는 먼저 요구사항을 문장으로 바꾸면 선택이 쉬워집니다. “현재 인덱스 이름이 이 값인 행”이면 loc, “정렬된 결과의 몇 번째 위치”이면 iloc입니다. 단순히 오류를 없애려고 loc을 iloc으로 바꾸면 다른 행을 읽을 수 있으므로, 접근 대상의 의미까지 확인해야 합니다.

운영 코드에서 다시 확인할 순서

오류가 반복되는 자동화라면 다음 순서로 로그를 남기면 원인을 좁히기 좋습니다.

  1. 오류가 난 표현식에서 사용한 키를 확인합니다.
  2. df.columns.tolist()와 repr 기반 열 이름을 확인합니다.
  3. df.index.tolist() 또는 인덱스의 대표 값을 확인합니다.
  4. 입력 파일의 구분자·헤더·index_col 설정을 확인합니다.
  5. set_index() 이후라면 해당 이름이 컬럼에서 인덱스로 이동했는지 확인합니다.
  6. 마지막으로 label 접근인지 위치 접근인지에 따라 loc 또는 iloc을 선택합니다.

이 흐름을 로그에 그대로 남기면 “컬럼이 있는데 왜 없다고 하지?”라는 추측 대신, 실패한 label과 현재 DataFrame 구조를 비교할 수 있습니다. 원본 열 이름을 정리해야 한다면 그 변경 규칙도 입력 변환 단계에 명시하고, 원본 의미를 훼손하지 않는지 함께 검토하십시오.

마무리

pandas KeyError는 컬럼 철자 하나만의 문제가 아닐 수 있습니다. 실제 열 label, CSV 파싱 결과, set_index() 이후의 구조, 그리고 loc·iloc이 각각 label과 position을 해석하는 방식을 분리해서 확인해야 올바른 수정 방향을 고를 수 있습니다.

이어서 확인할 질문

  • CSV를 읽었는데 컬럼이 한 개로 합쳐졌다면 실제 구분자와 read_csv 옵션이 일치하는지 확인합니다.
  • 행 번호를 선택하려면 position인지 index label인지 먼저 정한 뒤 iloc 또는 loc을 선택합니다.
  • set_index() 후 사라진 컬럼은 현재 인덱스 목록과 drop 동작을 함께 확인합니다.

참고 자료

Leave a Comment