Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬(Python) 중첩 딕셔너리 리스트를 Pandas 데이터프레임으로 변환하는 방법

개요

실무에서 파이썬은 CSV, JSON 등 다양한 형식의 여러 데이터 소스로부터 정보를 받게 되며, 이런 데이터는 파이썬의 리스트(list)나 딕셔너리(dictionary) 형태로 변환되곤 합니다. 하지만 pandas와 같은 라이브러리로 계산이나 분석을 수행하려면, 먼저 데이터를 데이터프레임(DataFrame) 구조로 바꿔야 합니다.

이 글에서는 요소가 중첩 딕셔너리(nested dictionary)로 구성된 파이썬 리스트를 pandas 데이터프레임으로 변환하는 방법을 단계별로 살펴봅니다.

변환 절차는 크게 세 단계로 이루어집니다.

  1. 중첩 딕셔너리 리스트에서 각 행(row)에 해당하는 데이터를 추출합니다.
  2. 미리 생성해 둔 빈 리스트에 행 데이터를 추가하기 위해 내부 for 반복문을 실행합니다.
  3. pandas 라이브러리의 DataFrame() 함수를 적용해 최종 데이터프레임을 만듭니다.

예제 코드

import pandas as pd

# 주어진 중첩 딕셔너리
data_list = [
    {
        "Fruit": [
            {"Price": 15.2, "Quality": "A"},
            {"Price": 19,   "Quality": "B"},
            {"Price": 17.8, "Quality": "C"}
        ],
        "Name": "Orange"
    },
    {
        "Fruit": [
            {"Price": 23.2, "Quality": "A"},
            {"Price": 28,   "Quality": "B"}
        ],
        "Name": "Grapes"
    }
]

rows = []

# 행 데이터 추출
for data in data_list:
    data_row = data['Fruit']
    n = data['Name']

    for row in data_row:
        row['Name'] = n
        rows.append(row)

# 데이터프레임으로 변환
df = pd.DataFrame(rows)
print(df)

위 코드를 실행하면 다음과 같은 결과가 출력됩니다.

실행 결과

   Price Quality    Name
0   15.2       A  Orange
1   19.0       B  Orange
2   17.8       C  Orange
3   23.2       A  Grapes
4   28.0       B  Grapes

"Orange"의 세 가지 품질 등급(A, B, C)과 "Grapes"의 두 가지 등급(A, B)에 대한 가격 정보가 각각 하나의 행으로 펼쳐져, 총 5개의 행을 가진 깔끔한 데이터프레임이 완성된 것을 확인할 수 있습니다.

pivot_table로 데이터 재구성하기

pivot_table 함수를 추가로 적용하면 원하는 형태로 데이터를 자유롭게 재배치할 수 있습니다. 과일 이름(Name)을 인덱스로, 품질(Quality)을 컬럼으로 지정하면 과일별·등급별 가격을 한눈에 비교할 수 있는 표가 만들어집니다.

예제 코드

import pandas as pd

# 중첩 딕셔너리 리스트 초기화
data_list = [
    {
        "Fruit": [
            {"Price": 15.2, "Quality": "A"},
            {"Price": 19,   "Quality": "B"},
            {"Price": 17.8, "Quality": "C"}
        ],
        "Name": "Orange"
    },
    {
        "Fruit": [
            {"Price": 23.2, "Quality": "A"},
            {"Price": 28,   "Quality": "B"}
        ],
        "Name": "Grapes"
    }
]

rows = []

# 행 데이터 추가
for data in data_list:
    data_row = data['Fruit']
    n = data['Name']

    for row in data_row:
        row['Name'] = n
        rows.append(row)

# 데이터프레임 생성 후 피벗 테이블 적용
df = pd.DataFrame(rows)

df = df.pivot_table(index='Name', columns=['Quality'],
                    values=['Price']).reset_index()
print(df)

위 코드를 실행하면 다음과 같은 결과가 출력됩니다.

실행 결과

Quality    Name Price            
                 A     B     C
0        Grapes  23.2  28.0 NaN
1        Orange  15.2  19.0 17.8

Grapes에는 C 등급 데이터가 없으므로 해당 칸은 NaN(결측값)으로 표시됩니다. 필요하다면 fill_value=0 옵션을 추가해 결측값을 0 등 원하는 값으로 대체할 수 있습니다.

참고: json_normalize로 더 간단하게 처리하기

동일한 작업은 pandas의 json_normalize() 함수를 사용하면 더욱 간결하게 처리할 수 있습니다. 중첩된 필드를 record_path로 지정하고 상위 필드를 meta로 전달하면, 앞서 반복문으로 수행했던 평탄화(flatten) 작업이 한 줄로 해결됩니다.

df = pd.json_normalize(
    data=data_list,
    record_path='Fruit',
    meta=['Name']
)
print(df)

마지막으로 실무 팁을 하나 덧붙이자면, 예제에서처럼 변수 이름을 list로 짓는 것은 피하는 것이 좋습니다. list는 파이썬의 기본 내장 타입이므로 변수명으로 사용하면 기존 내장 기능을 덮어써서(shadowing) 이후 코드에서 오류를 일으킬 수 있습니다. 위 예제에서는 이를 방지하기 위해 data_list라는 이름을 사용했습니다.