본문 바로가기
프로그래밍/Python

파이썬(Python) ast 모듈을 이용하여 문자(String) 타입의 리스트나 튜플, 딕셔너리를 리스트, 튜플, 딕셔너리 타입으로 변환하기 (feat. literal_eval)

by 부자 꽁냥이 2023. 1. 19.

csv나 Excel과 같은 데이터 테이블 읽다 보면 때때로 특정 칼럼에 리스트, 튜플 그리고 딕셔너리로 포함된 경우가 있다. 이를 Pandas 데이터프레임으로 불러오면 리스트(튜플, 딕셔너리)가 아닌 문자 타입으로 읽어지는 경우가 있다. 즉, 원래 객체 타입이 문자 타입으로 바뀐 것인데 ast 모듈의 literal_eval 함수를 사용하면 문자를 원래 객체 타입으로 바꿀 수 있다. 이번 포스팅에서는 해결하고자 하는 문제를 살펴보고 literal_eval 함수를 이용하여 문제를 어떻게 해결하는지 알아보고자 한다.


   literal_eval 사용법

1) 문제 확인

먼저 Pandas 데이터프레임을 하나 만들어보았다. 각 칼럼에 리스트, 튜플 그리고 딕셔너리를 갖도록 했다. 그러고 나서 각 칼럼의 첫 번째 원소 타입을 출력했다.

 

import pandas as pd

## 데이터프레임 생성
df = pd.DataFrame()
df['LIST'] = [[1,2,3], [4,5,6], [7,8,9]]
df['TUPLE'] = [(1,2,3), (4,5,6), (7,8,9)]
df['DICT'] = [{'a':'b'}, {'c':'d'}, {'e':'f'}]

## 칼럼 첫 번째 값 Type 확인
print(type(df['LIST'].iloc[0]))
print(type(df['TUPLE'].iloc[0]))
print(type(df['DICT'].iloc[0]))

 

 

결과를 보면 우리가 예상한대로 리스트, 튜플 그리고 딕셔너리 타입을 출력하는 것을 알 수 있다. 이제 이 데이터프레임을 엑셀로 저장한 뒤 다시 읽어보자. 그러고 나서 각 칼럼의 첫 번째 값의 타입을 살펴보자.

 

df.to_excel('./list.xlsx', index=False) ## 엑셀 저장 

new_df = pd.read_excel('./list.xlsx') ## 엑셀 파일 읽기

## 데이터 타입 출력
print(type(new_df['LIST'].iloc[0]))
print(type(new_df['TUPLE'].iloc[0]))
print(type(new_df['DICT'].iloc[0]))

 

 

!! 아까와는 다르게 모두 문자형으로 변한 것을 알 수 있다. 값을 확인해보자.

 

 

값을 확인해 보니 리스트가 홑따옴표에 감싸져 문자로 저장이 된 것이었다. 튜플과 딕셔너리도 마찬가지였다. 따라서 이러한 문자 타입을 본래 갖고 있던 타입으로 바꿔줘야 한다. 이때 사용하는 것이 아래에서 소개할 literal_eval이다.


2) literal_eval을 이용한 문제 해결

literal_eval의 사용법은 간단하다. 이 함수에 문자만 넣어주면 된다. 원래는 리스트(튜플, 딕셔너리)였던 데이터를 홑따옴표로 감싼 문자열을 다시 리스트(튜플, 딕셔너리)로 바꿔보자. 이때 literal_eval을 사용하기 전과 후로 나누어 데이터 타입의 변화를 출력해 보았다.

 

test_string = '[1, 2, 3]'
print(test_string, type(test_string))
res = literal_eval(test_string)
print(res, type(res))

 

 

코드를 실행하면 원래는 문자 타입(str)이었지만 literal_eval을 사용했더니 리스트(list)로 바뀐 것을 알 수 있다. 이제 이를 이용하여 앞에서 살펴본 문제를 해결해 보자. literal_eval을 사용하여 데이터의 타입을 바꾸고 각 칼럼의 첫 번째 값의 타입을 살펴보자.

 

## 데이터 본래 타입으로 변환
for col in new_df.columns:
    new_df[col] = new_df[col].map(lambda x:literal_eval(x))

## 데이터 타입 출력
print(type(new_df['LIST'].iloc[0]))
print(type(new_df['TUPLE'].iloc[0]))
print(type(new_df['DICT'].iloc[0]))

 

 

원래 의도했던 타입으로 잘 바뀐 것을 알 수 있다.


사실 데이터프레임을 피클(pickle)로 저장하면 원 데이터 타입이 변하지 않으므로 이러한 문제는 생기지 않는다. 하지만 가끔씩 남이 만들어준 데이터를 읽을 때 리스트가 문자로 된 경우가 있어서 이럴 때 literal_eval을 사용하여 원 객체 타입으로 바꿔줄 수 있다. 알아두면 유용하게 써먹을 수 있다.


댓글


맨 위로