| Week | Data Analysis | Difficulty | This Notebook |
|---|---|---|---|
| 1 | 서울시 인구 데이터 | ⭐️ | |
| 2 | 화장품 성분 데이터 | ⭐️⭐️⭐️ | 👈 |
| 3 | 올림픽 데이터 | ⭐️⭐️ | |
| 4 | 국가별 인터넷 사용률 데이터 | ⭐️⭐️ | |
| 5 | 전국 박물관/미술관 정보 표준 데이터 | ⭐️⭐️⭐️ | |
| 6 | 서울시 흡연율 통계 데이터 | ⭐️⭐️ | |
| 7 | 웹크롤링 | ⭐️ | |
| 8 | 서울시 지하철 호선별 역별 유/무임 승하차 인원 정보 데이터 | ⭐️⭐️ | |
| 9 | 서울시 교통사고 현황 (사고유형별) 통계 데이터 | ⭐️⭐️ | |
| 10 | 서울시 교통사고 현황 (사고유형별) 통계 + 서울시 차량통행속도 (구별/월별) 통계 + 서울시 인구밀도 (구별) 통계 | ⭐️⭐️⭐️ |
총 3단계 데이터 분석 상황 제시
1단계 DataFrame 불러오기 & 기초 전처리
2단계 전처리
3단계 Mapping
import pandas as pd
# 채점을 위한 코드입니다. 반드시 실행해주세요.
from grading import *
df_target = pd.read_csv('./datas/cosmetics.csv')
df_target = df_target.iloc[:5] # 5개의 row만 사용합니다
df_target


pip install tabula-pyimport tabula
import pickle
# module 'tabula' has no attribute 'read_pdf'
에러 발생하면, 아래 코드 주석 해제 후 실행
from tabula.io import read_pdf
# Tabula로 PDF 읽기 -> DataFrame List
ingredients_list = tabula.read_pdf('./datas/별첨1. 표준화명칭목록_220530.pdf', pages='all', lattice=True)
# DataFrame List를 Pickle로 저장
with open('./datas/ingredients_list.pkl', 'wb') as f:
pickle.dump(ingredients_list, f)
에서 TroubleShooting ➡️ EDA Level Test 02 tabula module error 부분 확인
from google.colab import drive
drive.mount('/content/drive')
# Pickle File 불러오기
import pickle
with open('./datas/ingredients_list.pkl', 'rb') as f:
ingredients_list_pkl = pickle.load(f)
Pickle을 이용해 Load한 ingredients_list_pkl를 하나의 DataFrame으로 합치세요.
조건1: 데이터는 index 기준으로 합치세요.
조건2: join없이 단순히 합치세요.
hint1: 20375개의 행이 만들어져야 합니다.
hint2: ingredients_list_pkl는 여러 DataFrame들이 Element로 들어있는 List입니다.
완료 후 결과 dataframe 변수를 check_01_01 함수에 입력하여 채점하세요.
ingredients_list_pkl

# 1-1
# pd.concat : 리스트에 있는 여러 DataFrame을 하나의 DataFrame으로 합침
# ignore_index=T/F: 이 옵션은 합치는 과정에서 원래의 index를 유지할 것인지를 결정합니다.
# False-DataFrame들의 index가 그대로 유지/True-index는 리셋되어 0부터 다시 시작
ingredients_df = pd.concat(ingredients_list_pkl, ignore_index=False)
ingredients_df

이 성분 사전 DataFrame에는 원본에는 없는 '\r' 이 아래와 같이 data 사이에 끼어 있습니다. 이 '\r'을 삭제하세요

hint1: '\r'를 대체 할 때 한글('표준 성분명', '구명칭')의 경우 띄어쓰기가 없고, 영어('표준 영문명', '구영문명)의 경우 띄어쓰기를 해야 합니다.
hint2: 모든 영문명의 경우 대문자로 시작합니다.
완료 후 결과 dataframe 변수를 check_01_02 함수에 입력하여 채점하세요.
#1-2
ingredients_df.reset_index(drop=True, inplace=True)
ingredients_df['표준 성분명'] = ingredients_df['표준 성분명'].replace('\r', "",regex = True)
ingredients_df['구명칭'] = ingredients_df['구명칭'].replace('\r', "", regex = True)
ingredients_df['표준 영문명'] = ingredients_df['표준 영문명'].replace('\r', " ", regex = True)
ingredients_df['구영문명'] = ingredients_df['구영문명'].replace('\r', " ", regex = True)
ingredients_df

pdf를 dataframe으로 전환하면서 일부 누락된 데이터가 있습니다. 아래 cell의 replace_dict는 현재값(key):변경할값(value)의 쌍으로 이루어져 있습니다. 이 replace_dict를 이용하여 성분사전 dataframe '표준 영문명' column의 값을 변경하세요.
완료 후 결과 dataframe 변수를 check_01_03 함수에 입력하여 채점하세요.
# 1-3
replace_dict = {
'Acetobacter/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitumit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia': 'Acetobacter/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitumit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia Ferment',
'Saccharomyces/Licorice Root/Rehmannia Glutinosa Root/Angelica Gigas Root/Ophiopogon Japonicus Root/Atractylodes Macrocephala Root/Paeonia Lactiflora Root/Anemarrhena Asphodeloides Root/Fraxinus Excelsior Bark/Asparagus Cochinchinensis/Phellodendron Amurense': 'Saccharomyces/Licorice Root/Rehmannia Glutinosa Root/Angelica Gigas Root/Ophiopogon Japonicus Root/Atractylodes Macrocephala Root/Paeonia Lactiflora Root/Anemarrhena Asphodeloides Root/Fraxinus Excelsior Bark/Asparagus Cochinchinensis/Phellodendron Amurense Bark Ferment Extract',
'Bacillus/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia': 'Bacillus/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia Ferment',
'Bifida/Angelica Gigas/Angelica Tenuissima Root/Antler Velvet/Rehmannia Glutinosa Root/Atractylodes Japonica Rhizome/Cnidium Officinale Root/Cordyceps Sinensis/Ledebouriella Seseloides Root/Licorice Root/Paeonia Lactiflora Root/Panax Ginseng': 'Bifida/Angelica Gigas/Angelica Tenuissima Root/Antler Velvet/Rehmannia Glutinosa Root/Atractylodes Japonica Rhizome/Cnidium Officinale Root/Cordyceps Sinensis/Ledebouriella Seseloides Root/Licorice Root/Paeonia Lactiflora Root/Panax Ginseng Root/Phellinus Linteus/Scutellaria Baicalensis Root Ferment',
'Leuconostoc/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia': 'Leuconostoc/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia Ferment',
'Saccharomyces/Anemarrhena Asphodeloides Root/Angelica Gigas Root/Asparagus Cochinchinensis/Atractylodes Macrocephala Root/Fraxinus Excelsior Bark/Licorice Root/Ophiopogon Japonicus Root/Paeonia Lactiflora Root/Phellodendron Amurense': 'Saccharomyces/Anemarrhena Asphodeloides Root/Angelica Gigas Root/Asparagus Cochinchinensis/Atractylodes Macrocephala Root/Fraxinus Excelsior Bark/Licorice Root/Ophiopogon Japonicus Root/Paeonia Lactiflora Root/Phellodendron Amurense Bark Ferment Extract',
'Saccharomyces/Camellia Japonica Flower/Castanea Crenata Shell/Diospyros Kaki Leaf/Paeonia Suffruticosa Root/Rhus Javanica/Sanguisorba Officinalis Root Extract': 'Saccharomyces/Camellia Japonica Flower/Castanea Crenata Shell/Diospyros Kaki Leaf/Paeonia Suffruticosa Root/Rhus Javanica/Sanguisorba Officinalis Root Extract Ferment Filtrate',
'Lactobacillus/Honeysuckle Flower/Licorice Root/Morus Alba Root/Pueraria Lobata Root/Schisandra Chinensis Fruit/Scutellaria Baicalensis Root/Sophora Japonica Flower': 'Lactobacillus/Honeysuckle Flower/Licorice Root/Morus Alba Root/Pueraria Lobata Root/Schizandra Chinensis Fruit/Scutellaria Baicalensis Root/Sophora Japonica Flower Extract Ferment Filtrate',
'Lactobacillus/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/Cinnamomum Cassia': 'Lactobacillus/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/Cinnamomum Cassia Ramulus Bark Ferment Filtrate',
'Saccharomyces/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia': 'Saccharomyces/Lycium Chinense Fruit/Rehmannia Glutinosa Root/Cuscuta Chinensis Fruit/Cistanche Deserticola/Zanthoxylum Piperitum Fruit/Chrysanthemum Morifolium Fruit/Poria Cocos/ Cinnamomum Cassia Ferment',
}
ingredients_df['표준 영문명'] = ingredients_df['표준 영문명'].replace(replace_dict)
ingredients_df

Kaggle에서 가져오는 데이터는 수정을 필요로 하는 경우가 있습니다. 제시된 Target DataFrame 또한 성분사전과 다른 표현을 쓰는 경우가 있어 해당 내용에 대해 수정을 하고자 합니다. 다음 조건에 맞게 Ingredients Column의 데이터를 수정하세요.
조건1: 맨 끝에 마침표('.')가 있다면 마지막 마침표만 제거하세요
조건2: '. May Contain'를 포함하고 있다면, '. May Contain' 이후의 데이터를 제거하세요
조건3: 아래의 replace_str_dict는 현재값(key):변경할값(value)의 쌍으로 이루어져 있습니다. 이 replace_str_dict를 이용하여 데이터를 변경하세요
완료 후 결과 dataframe 변수를 check_02_01 함수에 입력하여 채점하세요.
replace_str_dict = {
'Algae (Seaweed) Extract': 'Algae Extract',
'Citrus Aurantifolia (Lime) Extract': 'Citrus Aurantifolia (Lime) Fruit Extract',
'Eucalyptus Globulus (Eucalyptus) Leaf Oil': 'Eucalyptus Globulus Leaf Oil',
'Galactomyces Ferment Filtrate (Pitera)': 'Galactomyces Ferment Filtrate',
'Bacillus/Soybean/ Folic Acid Ferment Extract': 'Bacillus/Folic Acid/Soybean Ferment Extract',
'Butyrospermum Parkii (Shea Butter)': 'Butyrospermum Parkii (Shea) Butter',
'Sea Salt/Maris Sal/Sel Marin': 'Sea Salt',
'Parfum/Fragrance': 'Fragrance|Perfume|Parfum',
', Fragrance': ', Fragrance|Perfume|Parfum',
}
# 조건을 처리하는 함수 정의
def process_ingredients(ingredient, replace_str_dict):
# 조건 1: 맨 끝의 마침표 제거
if ingredient.endswith('.'):
ingredient = ingredient[:-1]
# 조건 2: '. May Contain' 이후 데이터 제거
if '. May Contain' in ingredient:
ingredient = ingredient.split('. May Contain')[0]
# 조건 3: replace_str_dict에 따른 문자열 변경
for key, value in replace_str_dict.items():
ingredient = ingredient.replace(key, value)
return ingredient
# 'Ingredients' 컬럼에 조건을 적용
df_target['Ingredients'] = df_target['Ingredients'].apply(lambda x: process_ingredients(x, replace_str_dict))
df_target

다음 조건에 맞게 앞서 수정한 'Ingredients' Column의 데이터를 변환하여 'Ingredients List' Column에 입력하세요.
조건1: 'Ingredients' Column의 각 데이터를 ', '(쉼표+띄어쓰기)로 분리하여 List로 변환하세요
조건2: 조건1에서 변경한 list의 각 Element 앞뒤의 공백이 있다면 공백을 삭제하세요
조건3: 'Ingredients List' Column을 새로 생성하여 조건1과 조건2에서 만든 list를 각 행에 맞게 입력하세요
완료 후 결과 dataframe 변수를 check_02_02 함수에 입력하여 채점하세요.
# 조건 1: 각 데이터를 ', '(쉼표+띄어쓰기)로 분리
df_target['Ingredients List'] = df_target['Ingredients'].apply(lambda x: x.split(', '))
# 조건 2: 각 Element 앞뒤의 공백이 있다면 공백을 삭제
df_target['Ingredients List'] = df_target['Ingredients List'].apply(lambda x: [ingredient.strip() for ingredient in x])
df_target

(아래 예시를 참고)성분사전(Ingredients Dictionary)를 이용하여 Target DataFrame의 'Ingredients List'를 각 성분에 Mapping되는 'Code List'로 만들고, 'Code List' Column을 만들어 Code List를 각 행에 맞게 입력하세요.

- 조건1: Ingredients List에 대응하는 Code List의 순서는 같아야 합니다.
hint1: '표준 영문명'에서 찾지 못한다면 '구영문명'으로도 찾아보세요
hint2: 대문자-소문자 차이가 있을 수 있습니다.
참고: 'Code'는 성분사전(Ingredients Dictionary)의 '성분코드'를 의미합니다.(Index가 아닙니다)
완료 후 결과 dataframe 변수를 check_03_01 함수에 입력하여 채점하세요.
def map_code_list(ingredients_list):
code_list = []
# 표준영문명 또는 구영문명에 해당하는 성분코드 조회
for ingredient in ingredients_list:
code = ingredients_df[(ingredient.lower() == ingredients_df['표준 영문명'].str.lower()) |
(ingredient.lower() == ingredients_df['구영문명'].str.lower())]['성분코드'].values
# 성분코드 존재 시 code list에 'code'추가
if len(code) > 0:
code_list.append(code[0])
# 성분코드 미존재 시 code list에 'none'추가
else:
code_list.append(None)
return code_list
df_target['Code List'] = df_target['Ingredients List'].apply(lambda x: map_code_list([ingredient.strip() for ingredient in x]))
df_target

(아래 예시를 참고) Target DataFrame의 Code List를 각 행 내에서 중복 없이 모두 합쳐 두 번 나온 수를 오름차순으로 정렬하고, 첫번째부터 다섯번째까지의 수들을 찾아 성분사전(Ingredients Dictionary)를 이용하여 해당 Code들의 DataFrame을 구하세요.
예시 DataFrame

이 DataFrame에서 나타난 Code 중 각 행 내에서 중복 없이 두 번 나온 Code는 [3, 9, 23, 34, 57, 234] 이고, 이 중 오름차순으로 첫번째부터 다섯번째까지의 수는 [3, 9, 23, 34, 57] 입니다.
성분사전(Ingredients Dictionary)에서 해당 code들의 DataFrame은 아래와 같습니다.

조건1: 중복 code는 없어야 합니다.
조건2: '두' 번 나온 수, 오름차순, 첫번째부터 다섯번째까지 다시 한번 확인하세요.
hint1: sorted(list, key=lambda x: func(x))
hint2: set()
hint3: list.count()
참고: 'Code'는 성분사전(Ingredients Dictionary)의 '성분코드'를 의미합니다.(Index가 아닙니다)
완료 후 결과 dataframe 변수를 check_03_02 함수에 입력하여 채점하세요.
from collections import Counter
# 1단계: 각 행의 'Code List'에서 중복 값 제거
def remove_duplicates(code_list):
return list(set(code_list))
df_target['Code List'] = df_target['Code List'].apply(remove_duplicates)
# 2단계: 모든 Code List에서 등장한 코드들의 출현 횟수 세기
def get_repeated_codes(df_target):
# 모든 코드 목록 추출 후 등장 횟수 계산
all_codes = [code for sublist in df_target['Code List'] for code in sublist]
code_counts = Counter(all_codes)
# 두 번 나온 코드만 필터링(None 제외)
repeated_codes = [code for code, count in code_counts.items() if count == 2]
repeated_codes = [code for code in repeated_codes if code is not None]
# 상위 5개의 코드 추출
repeated_codes.sort()
return repeated_codes[:5]
top_five_codes = get_repeated_codes(df_target)
# 3단계: 상위 5개의 코드에 해당하는 성분을 성분사전에서 찾기
result_df = ingredients_df[ingredients_df['성분코드'].isin(top_five_codes)]
result_df
