파이썬 pandas Length of values 오류: 데이터 길이와 인덱스 정렬 확인법

Length of values 오류는 새 열에 넣는 목록·배열의 길이가 대상 DataFrame의 행 수와 다를 때 주로 발생하며, 값 개수가 맞는데 결과가 어긋나면 Series의 인덱스 레이블 정렬을 확인해야 합니다. 다만 오류 문구가 길이 문제를 가리키더라도 목록·배열과 Series를 구분하지 않으면 수정 방향을 잘못 잡을 수 있습니다. 저는 이런 오류를 만나면 값을 자르거나 반복하기 전에 DataFrame의 행 수, 인덱스, 대입할 객체의 종류를 차례로 확인합니다.

먼저 오류를 세 가지 경우로 나눕니다

자동화 과정에서 필터링이나 집계를 거친 뒤 새 열을 붙일 때는 다음 세 가지를 구분하면 수정 방향이 분명해집니다.

  • 목록·NumPy 배열의 길이 불일치: 위치로 들어가는 값의 개수와 대상 행 수가 다릅니다. df["score"] = values에서 values가 raw 배열이면 DataFrame 인덱스 길이와 맞아야 합니다.
  • Series의 인덱스 정렬 문제: Series는 단순히 순서대로 복사되지 않고 인덱스 레이블을 기준으로 정렬됩니다. 값 개수가 같아도 레이블이 다르면 예상하지 않은 행에 들어가거나 대상에 없는 레이블이 빠질 수 있습니다.
  • DataFrame 생성 인자 문제: dict에 담긴 배열 길이가 서로 다르거나, 배열 데이터와 columns·index의 의미가 맞지 않으면 생성 단계에서 오류가 납니다.

오류 문구가 Length of values를 가리킨다면 첫 번째 경우부터 확인하고, 오류 없이 결과만 이상하다면 두 번째 경우를 의심하는 순서가 안전합니다.

1. 행 수와 대입 값의 길이를 함께 확인합니다

먼저 대상 DataFrame의 구조를 출력합니다.

print("shape:", df.shape)
print("len(df):", len(df))
print("index:", df.index)
print("values length:", len(values))

df.shape는 행·열 구조를, len(df)는 대입 대상 행 수를 파악하는 데 사용합니다. df.index까지 함께 보면 필터링 뒤 인덱스가 연속적이지 않은지 확인할 수 있습니다.

목록이나 NumPy 배열을 열에 넣는다면 길이를 맞춘 뒤 대입해야 합니다.

values = [90, 80, 70]

if len(values) != len(df):
    raise ValueError("대상 행 수와 결과 값의 개수가 다릅니다.")

df["score"] = values

여기서 중요한 것은 예외를 없애기 위해 values[:len(df)]로 자르거나, 같은 값을 반복해 길이만 맞추지 않는 것입니다. 그렇게 하면 어떤 입력에서 빠진 결과인지 알 수 없고 다른 행에 값이 배치될 수 있습니다. 외부 API나 집계 결과라면 결과가 부족한 이유를 로그로 남기고 작업을 보류하는 편이 데이터 무결성에 유리합니다.

2. 값 개수가 같아도 Series 인덱스를 봅니다

Series를 DataFrame 열에 대입할 때 pandas는 위치가 아니라 인덱스 레이블 기준으로 값을 맞춥니다. 다음처럼 Series의 순서가 DataFrame과 달라도 인덱스가 같으면 레이블에 맞춰 배치됩니다.

import pandas as pd

df = pd.DataFrame({"name": ["Kim", "Lee"]}, index=[101, 102])
result = pd.Series([80, 90], index=[102, 101], name="score")

df["score"] = result
print(df)

이 경우 101 행에는 90, 102 행에는 80이 들어갑니다. Series를 순서대로 넣고 싶었다면 인덱스 정렬을 기대하지 말고, 그 의도를 코드로 분명히 해야 합니다. 반대로 인덱스 기준 매칭이 목적이라면 대입 전에 대상 인덱스로 재정렬합니다.

result = result.reindex(df.index)

if result.isna().any():
    raise ValueError("대상 DataFrame에 대응하지 않는 결과가 있습니다.")

df["score"] = result

reindex(df.index) 뒤의 결측에는 대응하는 레이블이 없어서 생긴 값과 원래 Series에 있던 결측이 모두 포함될 수 있습니다. 결측을 허용할지, 원인 확인 후 중단할지는 업무 규칙으로 정해야 합니다. 대상 DataFrame에 없는 Series 인덱스는 대입 결과에 반영되지 않으므로, 입력 결과의 인덱스가 정말 대상 행의 식별자인지도 확인해야 합니다.

3. DataFrame을 새로 만들 때 columns와 index를 구분합니다

DataFrame 생성자에는 data, index, columns가 전달됩니다. 열 레이블이 없는 이차원 데이터를 전달할 때 columns는 열 이름을 지정하는 값이고, index는 행 레이블을 지정하는 값입니다.

import pandas as pd

rows = [["Kim", 90], ["Lee", 80]]
df = pd.DataFrame(rows, columns=["name", "score"], index=[101, 102])

dict로 만들 때는 각 배열 열의 길이가 서로 같아야 합니다.

data = {
    "name": ["Kim", "Lee"],
    "score": [90, 80],
}
df = pd.DataFrame(data)

인덱스를 따로 지정하지 않고 Series를 담은 dict로 생성하면 Series 인덱스의 합집합을 기준으로 정렬됩니다. 따라서 다음처럼 길이만 보고 판단하지 말고 인덱스도 함께 확인해야 합니다.

scores = pd.Series([90, 80], index=[101, 102])
df = pd.DataFrame({"name": ["Kim", "Lee"], "score": scores}, index=[101, 102])

새 DataFrame에서 인덱스를 직접 지정한다면 배열의 행 수와 지정한 인덱스의 길이도 일치해야 합니다. columns와 index를 서로 바꿔 전달하는 실수는 값 자체의 문제가 아니라 생성자의 축을 잘못 이해한 문제이므로, 생성 직후 df.index와 df.columns를 출력해 확인하는 것이 좋습니다.

조건부 대입은 대상 행을 먼저 확정합니다

필터링한 행에만 값을 넣는 경우에는 전체 DataFrame의 행 수가 아니라 조건에 맞는 대상 행 수가 기준이 됩니다. 다만 대입할 값의 순서가 필터 결과의 순서와 정확히 대응한다는 전제가 필요합니다.

import pandas as pd

df = pd.DataFrame({"score": [None, 80, None]})
mask = df["score"].isna()
new_scores = [70, 75]

target_count = mask.sum()
if len(new_scores) != target_count:
    raise ValueError("조건에 맞는 행과 새 값의 개수가 다릅니다.")

df.loc[mask, "score"] = new_scores

실무에서는 가능하면 이름이나 레코드 ID처럼 확인 가능한 키를 가진 Series를 만들고, reindex로 대상 행에 맞춘 뒤 대입하는 편이 안전합니다. 단순 위치 대입은 필터 조건이나 정렬 순서가 바뀌었을 때 조용히 다른 행을 갱신할 위험이 있습니다.

assign을 쓸 때도 같은 규칙을 적용합니다

DataFrame.assign()은 새 DataFrame을 반환하지만, 전달한 Series·배열·스칼라의 정렬과 대입 규칙은 열 대입과 같은 관점에서 확인해야 합니다.

scores = pd.Series([90, 80], index=df.index)
updated = df.assign(score=scores)

assign을 사용한다고 길이 검증이 사라지는 것은 아닙니다. 새 결과를 반환한다는 점은 파이프라인을 구성할 때 편리하지만, 외부 결과의 행 수와 인덱스가 맞는지 확인하는 책임은 여전히 호출 코드에 있습니다.

운영 판단: 맞출까, 보류할까

오류를 수정할 때는 다음 순서로 결정하면 됩니다.

  1. 행 기준 확인: 필터링·정렬·중복 제거 뒤의 len(df)와 df.index를 확인합니다.
  2. 값의 형태 확인: 목록·배열인지, 인덱스를 가진 Series인지 구분합니다.
  3. 대응 기준 선택: 위치 대입이면 대상 행 수와 길이를 비교하고, 키 기반 대입이면 Series 인덱스를 df.index에 맞춥니다.
  4. 누락 처리 결정: 대응하지 않는 값이 있으면 결측 허용, 재처리, 작업 보류 중 업무 규칙에 따라 선택합니다.
  5. 대입 후 검증: 새 열의 결측과 키별 결과를 확인하고 저장·전송 단계로 넘깁니다.

반복이나 슬라이싱으로 길이만 맞춘 코드는 오류 메시지를 없애도 데이터가 올바른지 보장하지 않습니다. 이 문제의 핵심은 “개수가 같은가”에서 끝나지 않고 “각 값이 어느 행을 의미하는가”까지 확인하는 데 있습니다.

마무리

pandas의 Length of values 오류는 먼저 DataFrame의 행 수와 목록·배열의 길이를 비교하면 원인을 좁힐 수 있습니다. 값 개수가 맞는데 결과가 어긋나면 Series 인덱스 정렬을 확인하고, DataFrame 생성 단계라면 data, index, columns의 축과 길이를 다시 봐야 합니다. 자동화에서는 길이를 억지로 맞추기보다 대응 키와 누락 처리 기준을 정한 뒤, 확인되지 않은 결과는 보류하는 것이 안전합니다.

참고한 공식 문서:

Leave a Comment