본문 바로가기
판다스/판다스 에러 강의

[python] unhashable type 에러

by 김판다t 2024. 10. 19.

 

unhashable type 에러

 

unhashable type 에러는 파이썬에서 해시 가능하지 않은 자료형을 부적절하게 사용하려 할 때 발생하는 에러입니다. 이 에러의 의미는, 리스트와 같은 자료형이 해시 가능(hashable)하지 않기 때문에 특정 상황에서 사용할 수 없다는 것을 나타냅니다. 참고로 리스트, 딕셔너리, 집합(set) 자료형이 해시 가능하지 않는 자료형입니다.(mutable) 대표로 리스트로 인해 발생하는 unhashable type 에러를 예로 살펴보겠습니다.

TypeError: unhashable type: 'list'

 

hashable의 개념

 

hashable하다는 것은 객체가 고유한 해시값(hash value)을 가질 수 있음을 의미합니다. 해시값은 해당 객체를 유일하게 식별할 수 있는 정수로, 파이썬에서는 주로 해시 테이블 기반 자료구조(예: 딕셔너리, 집합)에서 활용됩니다. hashable 객체는 반드시 불변(immutable)이어야 하며, 이는 객체의 값이 변경되지 않아야 해시값이 유지될 수 있음을 뜻합니다. 불변 객체의 대표적인 예로는 int, float, string, tuple, frozenset 등이 있습니다.

 

unhashable의 정의

 

unhashable은 객체가 고유한 해시값을 가질 수 없다는 의미로, 주로 변경 가능(mutable)한 자료형에 해당합니다. 리스트, 딕셔너리, 집합(set)과 같은 자료형은 해시 함수를 사용할 수 없으며, 이 때문에 이러한 자료형은 해시 테이블 기반의 자료구조에 포함될 수 없습니다.

 

리스트가 unhashable한 이유

 

리스트는 변경 가능(mutable)하기 때문에 내부의 값이 언제든지 변경될 수 있습니다. 값이 변할 경우, 고유한 해시값이 달라질 수 있기 때문에 리스트와 같은 자료형은 해시값을 가질 수 없습니다. 예를 들어, 리스트를 딕셔너리의 키로 사용하려 하면, 파이썬은 리스트가 변경 가능하다는 이유로 고유한 해시값을 제공할 수 없기에 unhashable type: 'list' 에러가 발생합니다.

 

unhashable type: 'list' 에러를 발생시키는 주요 상황

 

1. 리스트를 딕셔너리의 키로 사용하려는 경우

my_dict = {[1, 2, 3]: "value"} # 리스트는 unhashable하므로 에러 발생

 

2. 리스트를 집합 자료구조(set)에 넣으려는 경우

my_set = set([[1, 2, 3], [4, 5, 6]])  # 리스트는 unhashable하므로 에러 발생

 

3. 판다스에서 groupby와 transform을 사용할 때 여러 개의 함수를 리스트로 전달하려 하는 경우

import pandas as pd
# 예시 데이터 프레임 df 생성
data = {'name': ['Alice', 'Alice', 'Bob', 'Bob'], 'score': [10, 20, 30, 40]}
df = pd.DataFrame(data)

# groupby와 transform을 사용할 때 sum과 max 함수를 리스트로 전달
out = df.groupby('name')['score'].transform(['sum', 'max']) # 에러 발생

 

그룹바이 객체에 transform 함수를 적용할 때 여러 개의 함수를 리스트로 전달하려 하면, transform 함수는 해시 가능한 단일 함수만을 허용하므로, 이 상황에서도 동일한 에러가 발생할 수 있습니다. (그룹 바이 객체가 아닌 데이터 프레임에 transform 함수를 적용하는 것은 가능합니다.)

# groupby 없이 transform을 적용할 때는 복수의 함수를 리스트로 전달 가능하다.
out = df.transform(['rank', 'shift']) # 에러가 발생하지 않음

 

4. 판다스에서 리스트가 셀에 포함되어 있는 데이터 프레임을 기준으로 groupby를 수행하는 경우

import pandas as pd
# 리스트가 포함된 데이터프레임 생성
data = {
    'name': [['Alice', 'Bob'], ['Alice', 'Bob'], 
             ['Charlie', 'Alice'], ['Charlie', 'Alice']], 
    'score': [10, 20, 30, 40]
}
df = pd.DataFrame(data)

# name 열에 리스트가 포함된 상태로 name 열을 기준으로 groupby 수행
out = df.groupby('name')['score'].sum() # 에러 발생

 

 

scores 열에는 각 셀이 리스트를 포함하고 있습니다. groupby('scores')를 수행하려고 하면, 리스트는 unhashable한 타입이기 때문에 unhashable type: 'list' 에러가 발생합니다. 이 에러는 리스트를 그룹화 키로 사용할 수 없기 때문에 발생합니다. 

 

일반적으로 판다스 데이터프레임 셀에 리스트, 딕셔너리, 튜플 등의 복합 자료형을 넣는 것은 권장되지 않으며, 그룹화 키로 사용하려면 리스트 대신 튜플과 같은 불변형(immutable) 자료형을 사용하는 것이 좋습니다.

 

혹은 다음과 같은 2차원 리스트를 생성해 그룹화의 키를 그루퍼로 생성하는 것도 방법입니다. (그루퍼는 그자체가 키가 아니라, 키의 집합이므로 키의 집합은 리스트로 묶을 수 있습니다.)

grp = list(map(list, zip(*df['name']))) # 그루퍼 생성
out = df['score'].groupby(grp).sum()

 

 

결론

 

unhashable type 에러는 변경 가능(mutable)한 객체에 해시가 필요한 상황에서 발생합니다. 파이썬에서는 리스트와 같은 변경 가능한 객체가 고유한 해시값을 가질 수 없기 때문에, 딕셔너리의 키나 집합의 요소, 그룹화의 키 등으로 사용할 수 없습니다.


교보문고 구매 페이지, 알라딘 구매 페이지yes24 구매 페이지