본문 바로가기

TIL

[240206] 중첩 딕셔너리? JSON 포맷 데이터프레임으로 평면화

* 자료 출처: Kaggle - Google Analytics Customer Revenue Prediction

 

1. 문제 배경

- 심화 프로젝트 분석 데이터셋의 각 칼럼값이 여러 딕셔너리 값이 나열된 듯한 모양을 함 

['device'] 칼럼 값 예시

{"browser": "Safari", "browserVersion": "not available in demo dataset", "browserSize": "not available in demo dataset", "operatingSystem": "iOS", "operatingSystemVersion": "not available in demo dataset", "isMobile": true, "mobileDeviceBranding": "not available in demo dataset", "mobileDeviceModel": "not available in demo dataset", "mobileInputSelector": "not available in demo dataset", "mobileDeviceInfo": "not available in demo dataset", "mobileDeviceMarketingName": "not available in demo dataset", "flashVersion": "not available in demo dataset", "language": "not available in demo dataset", "screenColors": "not available in demo dataset", "screenResolution": "not available in demo dataset", "deviceCategory": "mobile"}

 

- 각 딕셔너리형 칼럼을 데이터프레임화하고자 json.loads와 for문 활용해서 (1차) 성공 

└ 하지만, 일부 데이터 내 딕셔너리 value에 해당하는 값에 딕셔너리 형태 값이 한 번 더 중첩되어 있음을 확인! 

['trafficSource'] 칼럼 값 예시

{"campaign": "AW - Dynamic Search Ads Whole Site", "source": "google", "medium": "cpc", "keyword": "6qEhsCssdK0z36ri", "adwordsClickInfo": {"page": "1", "slot": "Top", "criteriaParameters": "not available in demo dataset", "gclId": "Cj0KEQjwxqS-BRDRgPLp0q2t0IUBEiQAgfMXRBRI7rtb79aCyB-UUNNHh1V712wows-T-MlL9VW-8ZEaAhqd8P8HAQ", "adNetworkType": "Google Search", "isVideoAd": false}}

 

- if 및 for 문을 활용해 중첩된 내용을 풀어보고자 했으나 실패하고 json_normalize 함수 활용하여 해결 

 

2. JSON과 Dictionary 차이  

1) JSON

- 키-값 쌍이나 시리얼화 가능한 값으로 구조화된 데이터를 표현하기 위한 텍스트 기반 표준 포맷 (파일 형식)

- JavaScript Object Notation의 약어로 Javascript 객체 문법이라는 뜻

- 데이터 입출력에 많이 사용되는 경량의 데이터 교환 형식   

- 기본적으로 Object, Array, String, Number, Boolean, null 자료형 사용 가능

 

2) 딕셔너리(Dictionary)
- Key와 Value를 한 쌍으로 가지는 파이썬 자료형

- Key에 내부적으로 hash값 저장
- 내부 요소는 인덱스 개념이 아니라 순서가 없음

 

* 출처: https://hyundolog.tistory.com/7

 

3. 완성 코드 

import pandas as pd 
import json

# 딕셔너리 모양 문자열 칼럼을 데이터프레임으로 펼치기 
def get_columns(columns_list: list):
    """" 딕셔너리 모양으로 들어간 문자열 칼럼을 데이터 프레임으로 변환해주는 함수  
    Args:
        columns_list(list): df_origin(pd.DataFrame)에서 변환이 필요한 칼럼명 리스트 

    Returns:
        pd.DataFrame: 데이터프레임
    """""
    df = df_origin.copy()

    for col in columns_list:
        change_df = pd.json_normalize(json.loads(row) for row in list(df[col]))
        change_df.columns = [f'{col}.{subcol}' for subcol in change_df.columns]
        df = df.drop(col, axis=1)
        df = pd.concat([df, change_df], axis = 1)
    return df

json_columns = ['device', 'geoNetwork', 'totals', 'trafficSource']
df = get_columns(json_columns)
df.info()

 

- 분리 완료된 칼럼 일부

 

[회고]

- 처음엔 JSON이 특정한 자료 형태가 아닌, 라이브러리 이름이라고 생각함 

- 파이썬으로 중첩된 다중 딕셔너리 형태의 데이터셋을 유연하게 다뤄보고자 json_normalize 없이 각 값들을 빼내는 작업 시도
└ 내장 함수를 활용해 여러 코드를 짜보며 꼬박 이틀을 고심했으나 결국 실패
 

- (결론) 지나치게 안 풀리는 문제는 적당히 고민해보고 필요한 라이브러리를 적당히 가져다 쓸 것