최종 프로젝트 : 결측치 보완 2
다른 결측치들도 무난하게 잘 채워 가는 듯 했다.
하지만, 지금까지 계속 발목을 잡았던 카테고리가 이번에도 문제였다.
leafCategoryIds 결측치
eaf_category 가 각 row마다 쪼개서 나온 (depth 기준) 최하위 category_id 를
leaf_category로 가져오는 바람에 L2, L3, L6 등 다 혼재되어 있음
df['leafCategoryId_1'].value_counts() >>> 11,086
- 해결 시도
- leafCategoryId_1 탐색 시작
- 같은 id (100979)인데도 이름이 다 다르게 나와서 의문을 가짐 → 이름 추출했던 코드 다시 뜯어보기 시작
- # 리프 카테고리 이름 추출 def get_leaf_names(categories, leaf_ids): return [ cat["categoryName"] for cat in categories if cat.get("categoryId") in leaf_ids ] df["leaf_category_names"] = df.apply( lambda row: get_leaf_names(row["categories"], row["leafCategoryIds"]), axis=1 )
- df[['leafCategoryId_1','leaf_category_names']].value_counts()
- leafCategoryId_1 탐색 시작
- 이유 & 해결 방안
- leafCategoryIds 에서 이름을 추출할 때, leafCategoryIds리스트에 있는 모든 이름을 가져옴
- Gifts만 나오게 하는 것을 목표로 코드 제작
- 이름 추출할 코드를 leafCategoryIds가 아닌 분리한 leafCategoryId_1에서 추출
- categories컬럼에서 이름을 추출해야 하기 때문에, categories 컬럼을 복원
import ast df1['categories'] = df1['categories'].apply(lambda x: ast.literal_eval(x) if isinstance(x, str) else x) def extract_leaf_category_name(row): try: if isinstance(row['categories'], list): for cat in row['categories']: if str(cat.get('categoryId')) == str(row['leafCategoryId_1']): return cat.get('categoryName') except: pass return None df1['leafCategoryName'] = df1.apply(extract_leaf_category_name, axis=1)
- Gifts만 나오게 하는 것을 목표로 코드 제작
- Ex) Gifts, [Gifts, Baby Jewellery] , [Gifts, Baby Showers], ….
- leafCategoryIds 에서 이름을 추출할 때, leafCategoryIds리스트에 있는 모든 이름을 가져옴
- 새로운 문제 발생
- leafCategoryId_1 는 같지만, leafCategoryName 이 다름
- 국가별로 다르게 정의 되어있는 카테고리 이름 때문인 것으로 추측
- US의 leafCategoryId 를 기반으로 다시 정리 해보자!
- 1차 시도
- leafCategoryId의 최빈값을 기준으로 이름 선택하기
- 최빈값이 US가 아닐 확률이 있어, 위험성 존재
# 1. ID 기준으로 가장 많이 쓰인 이름만 남김 id_to_name = ( df.groupby(["leafCategoryId_1", "leafCategoryName"]) .size() .reset_index(name="count") .sort_values(["leafCategoryId_1", "count"], ascending=[True, False]) .drop_duplicates("leafCategoryId_1") # ID 기준으로 대표 name 하나만 ) # 2. 대표 이름 기준으로 df에 다시 붙이기 df = df.drop(columns=["leafCategoryName"], errors='ignore') # 혹시 기존 컬럼 있으면 삭제 df = df.merge(id_to_name[["leafCategoryId_1", "leafCategoryName"]], on="leafCategoryId_1", how="left")
- 2차 시도
- US 데이터를 기준으로 최빈값의 이름 선택하기
- leafCategoryId의 고유값도 같이 감소해서 원인파악 필요
# 먼저 US 데이터만 필터링 df_us = df[df['listingMarketplaceId'] == 'EBAY_US'].copy() # US 데이터 기준으로 ID별 최빈 이름 구하기 id_to_name_us = ( df_us.groupby(["leafCategoryId_1", "leafCategoryName"]) .size() .reset_index(name="count") .sort_values(["leafCategoryId_1", "count"], ascending=[True, False]) .drop_duplicates("leafCategoryId_1") # ID 기준으로 대표 name 하나만 ) # 기존 컬럼 삭제 후 merge (전체 df 기준으로 merge → US 기준 대표 name 사용) df = df.drop(columns=["leafCategoryName"], errors='ignore') df = df.merge(id_to_name_us[["leafCategoryId_1", "leafCategoryName"]], on="leafCategoryId_1", how="left")
- 1차 시도
'TIL (Today I Learn)' 카테고리의 다른 글
TIL [내배캠] 80일차 (0) | 2025.06.13 |
---|---|
TIL [내배캠] 79일차 (1) | 2025.06.12 |
TIL [내배캠] 77일차 (0) | 2025.06.10 |
TIL [내배캠] 76일차 (0) | 2025.06.09 |
TIL [내배캠] 75일차 (1) | 2025.06.05 |