1. 스타벅스 옆엔 이디야와 올리브영이 있다?

https://kid.chosun.com/site/data/html_dir/2022/06/02/2022060202963.html

 

프랜차이즈 브랜드 立地<입지> 선택의 법칙… 스타벅스 옆엔 이디야가 있다?

 

kid.chosun.com

 

2. 스타벅스 정보 크롤링

스타벅스 한 매장 li 박스

import time
# re : 정규표현식 모듈
import re
import pandas as pd
from selenium import webdriver
# ActionChains: 마우스나 키보드와 같은 복잡한 사용자 상호작용을 시뮬레이션하는 데 사용
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
# WebDriverWait: 특정 요소가 나타날 때까지 대기하는 데 사용
from selenium.webdriver.support.ui import WebDriverWait
# expected_conditions: 특정 조건이 충족될 때까지 대기하는 데 사용
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup

def fetch_starbucks():
    starbucks_url = 'https://www.starbucks.co.kr/index.do'
    driver = webdriver.Chrome()
    driver.maximize_window()    # 브라우저 창 최대화
    driver.get(starbucks_url)
    time.sleep(1)

    # '매장 찾기' 버튼 클릭
    action = ActionChains(driver)
    # 첫 번째 메뉴인 'STORE'에 마우스 오버
    first_tag = driver.find_element(By.CSS_SELECTOR,'#gnb > div > nav > div > ul > li.gnb_nav03')
    # '매장 찾기' 버튼을 검사 후 a태그로 copy -> selcetor로 변경
    second_tag = driver.find_element(By.CSS_SELECTOR,'#gnb > div > nav > div > ul > li.gnb_nav03 > div > div > div > ul:nth-child(1) > li:nth-child(3) > a')
    
    # STORE 메뉴에 마우스 오버 후 '매장 찾기' 클릭
    action.move_to_element(first_tag).move_to_element(second_tag).click().perform()
    
    # 최대 10초까지 기다리기 -> 서울 클릭할 수 있는지 체크만 해준다.
    seoul_tag = WebDriverWait(driver,10).until(
        # 클릭할 수 있는지 테스트
        EC.element_to_be_clickable(
            (By.CSS_SELECTOR,'#container > div > form > fieldset > div > section > article.find_store_cont > article > article:nth-child(4) > div.loca_step1 > div.loca_step1_cont > ul > li:nth-child(1) > a')
        )
    )
    seoul_tag.click()
    
    # 데이터 저장할 리스트 준비
    store_list = []
    addr_list = []
    lat_list = []
    lng_list = []
    
    WebDriverWait(driver, 5).until(
        # 이 안에 돔 요소가 있는지 확인
        EC.presence_of_all_elements_located((
            By.CLASS_NAME,'set_gugun_cd_btn'
        ))
    )
    gu_elements = driver.find_elements(By.CLASS_NAME,'set_gugun_cd_btn')
    
    WebDriverWait(driver, 5).until(
        # 클릭할 수 있는지 확인
        EC.element_to_be_clickable(
            (By.CSS_SELECTOR,'#mCSB_2_container > ul > li:nth-child(1) > a')
        )
    )
    gu_elements[0].click()
    
    WebDriverWait(driver, 5).until(
        EC.presence_of_all_elements_located(
            (By.CLASS_NAME,'quickResultLstCon')
        )
    )    
    
    req = driver.page_source
    soup = BeautifulSoup(req, 'html.parser')
    stores = soup.find('ul', class_='quickSearchResultBoxSidoGugun').find_all('li')
    
    for store in stores:
        store_name = store.find('strong').text
        store_addr = store.find('p').text
        store_addr = re.sub(r'\d{4}-\d{4}$', '', store_addr).strip()
        store_lat = store['data-lat']
        store_lng = store['data-lng']
        
        # 데이터 리스트에 추가
        store_list.append(store_name)
        addr_list.append(store_addr)
        lat_list.append(store_lat)
        lng_list.append(store_lng)
        
    df = pd.DataFrame({
        'store': store_list,
        'addr': addr_list,
        'lat': lat_list,
        'lng': lng_list
    })
    
    driver.quit()  # 브라우저 종료
    return df
    
starbucks_df = fetch_starbucks()
# sig 붙이면 엑셀에서 한글 깨짐 방지
starbucks_df.to_csv('starbucks_seoul.csv', index=False, encoding='utf-8-sig')   
print('스타벅스 매장 정보가 starbucks_seoul.csv에 저장되었습니다.')

 

 

3. 데이터 전처리

import pandas as pd

df_starbucks = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/Python_colab/Web Service/11. 데이터 분석/data/starbucks_seoul.csv')
df_starbucks
df_starbucks = df_starbucks.set_axis(['지점명','지점주소','지점위도','지점경도'],axis=1).reset_index(drop=True)
df_starbucks
df =pd.read_csv('/content/drive/MyDrive/Colab Notebooks/Python_colab/Web Service/11. 데이터 분석/data/소상공인시장진흥공단_상가(상권)정보_20250331/소상공인시장진흥공단_상가(상권)정보_서울_202503.csv',low_memory=False)
df.head()
df.info()
shop = ['이디야', '이디아커피', '올리브영', '컴포즈커피', '빽다방', '백다방', '메가커피', '메가엠지씨', '메가MGC']
# 메가커피(메가엠지씨) 데이터 필터링
# contains(): 특정 문자열 포함 여부에 따라 True, False를 반환
# case=False: 대소문자를 구분하지 않겠다는 설정
# na=False: 결측치(NaN) 처리. 결측치가 있는 경우 False로 간주하여 결과에 포함되지 않음
df[df["상호명"].str.contains("메가엠지씨", case=False, na=False)]
df[df["상호명"].str.contains("메가커피", case=False, na=False)]
df[df["상호명"].str.contains("메가MGC", case=False, na=False)]
# 한번에 다 찾기
df[df["상호명"].str.contains('메가커피|메가엠지씨|메가MGC', case=False, na=False)]
df_shop = df.copy()

# extract(): 특정 문자열을 포함하고 있으면 그 문자열을 반환, 포함하고 있지 않으면 NaN을 반환
df_shop['상호명'] = df_shop['상호명'].str.extract('({})'.format('|'.join(shop)))

# shop = ['이디야', '이디아커피', '올리브영', '컴포즈커피', '빽다방', '백다방', '메가커피', '메가엠지씨', '메가MGC']
# 이디야|이디아커피|올리브영|컴포즈커피|빽다방|백다방|메가커피|메가엠지씨|메가MGC
# 위에 해당되는 상호명 제외하고 다른 상호명은 다 NaN으로 날리기
df_shop['상호명']

# subset : 특정 컬럼이 아니면 다 지움
df_shop = df_shop.dropna(subset=['상호명']).iloc[:, [0, 1, 14, 37, 38]].reset_index(drop=True)
df_shop

# 상호명 통일시키기
df_shop['상호명'] = df_shop['상호명'].str.replace('메가엠지씨', '메가커피', regex=False)
df_shop['상호명'] = df_shop['상호명'].str.replace('메가MGC', '메가커피', regex=False)
df_shop['상호명'] = df_shop['상호명'].str.replace('이디아커피', '이디야', regex=False)
df_shop['상호명'] = df_shop['상호명'].str.replace('백다방', '빽다방', regex=False)
df_shop

# 상호명 통합됐는지 확인하기
df_shop[df_shop['상호명'].str.contains('메가엠지씨', na=False)]
print(df_shop.shape)
print(df_starbucks.shape)

# (2310, 5)
# (644, 4)
# cross-join으로 서울 전역을 다 연결시킨다. 
# 그 중에서 가장 최단거리를 가져오면 된다.
# cross : 하나당 모두 다
df_cross = df_shop.merge(df_starbucks, how='cross')
df_cross

# 1487640 rows × 9 columns

 

4. Haversine eqn

Haversine 공식은 구체(구면) 위의 두 점(위도와 경도로 표시됨) 사이의 최단 거리(대원 거리, great-circle distance)를 계산하는 방법입니다. 이 공식은 GPS 좌표(위도와 경도)를 활용하여 지구 표면 위의 거리 계산에 널리 사용됩니다.

 

** 유클리드 거리 & 맨하탄 거

 

 

from haversine import haversine
# 모든 행에 lambda식으로 정리
# 위도, 경도 : 서울 상업지
# 지점위도, 지점경도 : 스타벅스
df_cross['거리'] = df_cross.apply(lambda x: haversine([x['위도'], x['경도']], [x['지점위도'], x['지점경도']], unit='m'), axis=1)
df_cross
# 상가업소번호로 그룹을 맺고 거리가 짧은거 추출
# 개별 매장들과 스타벅스와의 최소 거리
df_dis = df_cross.groupby(['상가업소번호','상호명'])['거리'].min().reset_index()
df_dis

# 각 프렌차이즈 별 스타벅스와의 평균 거리
df_dis.groupby('상호명')['거리'].mean()

# agg(): 다중 집계작업을 간단하게 해주는 함수
df_dis.groupby(['상호명'])['거리'].agg(['mean','count'])

# 거리를 입력하면 프렌차이즈 별 스타벅스와의 평균거리와 매장개수를 출력하는 함수
def distance(x):
    dis = df_dis['거리'] <= x
    return df_dis[dis].groupby('상호명')['거리'].agg(['mean', 'count'])

# 100m 이내
distance(100)

 

5. 차트 시각화

!pip install pandasecharts
df_100 = distance(100).reset_index()
df_100
import IPython
from pandasecharts import echart

df_100.echart.pie(x='상호명', y='count', figsize=(600, 400),
                  radius=['20%', '60%'], label_opts={'position':'outer'},
                  title='커피 프렌차이즈의 입점전략은 과연 스타벅스 옆인가?',
                  legend_opts={'pos_right':'0%', 'orient':'vertical'},
                  subtitle='100m 이내 매장수', init_opts={'bg_color': 'white'}).render()

IPython.display.HTML(filename='render.html')

from pyecharts.charts import Timeline, Grid

tl = Timeline({'width':'600px', 'height':'400px'})

for i in [1000, 100, 50, 30]:
    df_d = distance(i).reset_index()
    pie1 = df_d.echart.pie(x='상호명', y='count', figsize=(600, 400),
                    radius=['20%', '60%'], label_opts={'position':'outer'},
                    title='커피 프렌차이즈의 입점전략은 과연 스타벅스 옆인가?',
                    legend_opts={'pos_right':'0%', 'orient':'vertical'},
                    subtitle='{}m 이내 매장수'.format(i), init_opts={'bg_color': 'white'})
    tl.add(pie1, '{}m'.format(i)).render()
IPython.display.HTML(filename='render.html')

1. 서울 열린데이터 광장

서울 열린데이터 광장(Seoul Open Data Plaza)은 서울시에서 운영하는 공공데이터 개방 플랫폼입니다. 시민, 연구자, 기업 등이 서울시에서 생성한 다양한 공공데이터를 자유롭게 활용할 수 있도록 제공하고 있습니다. 이를 통해 데이터 기반의 창의적인 아이디어와 혁신을 촉진하며, 시민들의 정보 접근성을 높이고 공공서비스를 개선하는 데 기여하고 있습니다.

https://data.seoul.go.kr/

 

열린데이터광장 메인

데이터분류,데이터검색,데이터활용

data.seoul.go.kr

 

 

2. 서울시 공공자전거 실시간 대여정보

1. 인증키를 발급 받습니다.

2. "서울시 공공자전거 실시간 대여정보" 를 검색합니다.

import requests # 서버에 붙어서 링크 가져오는 모듈
import folium
import json
import pandas as pd
import warnings
warnings.filterwarnings('ignore')

base_url = 'http://openapi.seoul.go.kr:8088/인증키/json/bikeList/1/1000/'
response = requests.get(base_url)
response

json_data = response.json()
json_data
json_data.get("rentBikeStatus", {})
# rentBikeStatus 기준으로 데이터 가져오기
json_data.get("rentBikeStatus", {}).get("RESULT", {}).get("CODE", "")
# rentBikeStatus 에서 RESULT에서의 CODE 상태 가져오기
# INFO-000
json_data["rentBikeStatus"]["RESULT"]["CODE"]
# INFO-000
# 위 처럼 파싱할 경우, 키를 못가져왔을 때 바로 에러남
def fetch_bike_data():
    base_url = "http://openapi.seoul.go.kr:8088/인증키/json/bikeList/"
    start = 1
    end = 1000
    step = 1000
    data_frames = []

    while True:
        url = f"{base_url}{start}/{end}/"
        response = requests.get(url)
        # 응답 에러 날 경우
        if response.status_code != 200:
            print(f"Status Code: {response.status_code}")
            break
        
        json_data = response.json()

        try:
            rent_bike_status = json_data["rentBikeStatus"]
            result_code = rent_bike_status["RESULT"]["CODE"]
        except KeyError:
            print("JSON 오류")
            break
        
        # INFO-000 : 정상
        # INFO-100 : 유효키 없음
        # INFO-200 : 데이터 없음
        if result_code == "INFO-200":
            print("데이터 없음")
            break
        elif result_code == "INFO-000":
            print(f"시작: {start} 끝: {end}.")
            try:
                bike_data = rent_bike_status["row"]
                if bike_data:
                	# 딕셔너리는 바로 데이터프레임으로 만들 수 있음
                    df = pd.DataFrame(bike_data)
                    data_frames.append(df)
            except KeyError:
                print("데이터를 찾을 수 없음")
        else:
            print(f"result code: {result_code}")
            break

        start += step
        end += step

    if data_frames:
    	# 인덱스를 포함하지 않고! 인덱스 새로 만들 예정
        final_df = pd.concat(data_frames, ignore_index=True)
        return final_df
    else:
        return pd.DataFrame()

 

bike_data_df = fetch_bike_data()

 

bike_data_df

bike_data_df.info()

'''
rackTotCnt	거치대개수	
parkingBikeTotCnt	자전거주차총건수	
shared	거치율	
stationLatitude	위도	
stationLongitude	경도	
stationId	대여소ID	
stationName	대여소이름	
'''
bike_data_df.columns
bike_data_df.shape
# 위도 & 경도를 float 형으로 변환
bike_data_df['stationLongitude'] = bike_data_df['stationLongitude'].astype(float)
bike_data_df['stationLatitude'] = bike_data_df['stationLatitude'].astype(float)
# 가지고 있는 위경도의 평균을 구해서 지도 노출
bike_map = folium.Map(location=[bike_data_df['stationLatitude'].mean(),
                                bike_data_df['stationLongitude'].mean()],
                                zoom_start=12)
                                
# iterrows : 행 자체는 가져오면서 인덱스 번호를 넣어주는 ...
for index, data in bike_data_df.iterrows():
    popup_str = '{} 자전거주차총건수:{}대'.format(
        data['stationName'], data['parkingBikeTotCnt']
    )
    popup = folium.Popup(popup_str, max_width=600)
    folium.Marker(location=[data['stationLatitude'], data['stationLongitude']],
                  popup=popup).add_to(bike_map)

bike_map

'Python' 카테고리의 다른 글

커피 프랜차이즈의 입점전략  (3) 2025.07.22
소상공인시장진흥공단_상가정보 데이터셋  (3) 2025.07.21
Online Retail  (0) 2025.07.21
Matplotlib  (0) 2025.07.21
Pandas  (0) 2025.07.17

1. 공공데이터

공공데이터(data.go.kr)는 대한민국 정부에서 운영하는 공공데이터 포털로, 공공기관이 보유한 다양한 데이터를 국민과 기업, 개발자 등에게 개방하여 활용할 수 있도록 제공하는 플랫폼입니다. 데이터를 파일 형식(Excel, CSV 등)으로 다운로드하거나, API 형태로 실시간 연동하여 사용할 수 있습니다.

 

1. "소상공인시장진흥공단_상가(상권)정보"을 검색 후  압축파일을 다운로드합니다.

2. 압축을 해제하고 "서울" csv 데이터를 구글드라이브에 업로드합니다.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

shop = pd.read_csv('/본인의 구글드라이브 경로/소상공인시장진흥공단_상가(상권)정보_서울_202409.csv', low_memory=False)
shop

 

pd.set_option('display.max_columns', 40)
shop

 

shop.info()

 

shop.columns

 

# 데이터 전처리 - 사용할 컬럼만 골라쓰기
view_columns = ['상호명', '지점명', '상권업종대분류명', '상권업종중분류명',
                '상권업종소분류명', '시도명', '시군구명', '도로명', '도로명주소',
                '경도', '위도']

shop = shop[view_columns]
shop.head()

 

shop.isnull().sum()

 

!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf

plt.rc('font', family='NanumBarunGothic')

 

# 산점도 그리기
plt.figure(figsize=(6, 8))  # 그래프 크기 설정
plt.scatter(shop['경도'], shop['위도'])  # 산점도 그리기
plt.xlabel('경도')  # x축 레이블
plt.ylabel('위도')  # y축 레이블
plt.grid(True)  # 그리드 추가
plt.show()  # 그래프 출력

len(shop)

 

shop.loc[shop['도로명주소'].str.startswith('서울')]

 

shop.loc[~shop['도로명주소'].str.startswith('서울')]

 

 

2. Seaborn

Seaborn은 Python의 데이터 시각화 라이브러리로, Matplotlib 위에 구축되어 데이터를 더 간단하고 쉽게 시각화할 수 있도록 설계되었습니다. 주로 통계적 데이터 시각화에 초점이 맞춰져 있으며, 다양한 차트와 스타일 옵션을 제공합니다.

pip install seaborn

 

import seaborn as sns

plt.figure(figsize=(14, 10))
sns.scatterplot(data=shop, x='경도', y='위도', hue='시군구명')

shop.head()

 

shop['상권업종대분류명'].value_counts()

 

shop_edu = shop[shop['상권업종대분류명'] == '교육']
shop_edu

 

shop_edu.shape

 

plt.figure(figsize=(14, 10))
sns.scatterplot(data=shop_edu, x='경도', y='위도', hue='상권업종중분류명')

shop_edu_etc = shop_edu[shop_edu['상권업종중분류명'] == '기타 교육']
shop_edu_etc

 

shop_edu_etc.shape

 

plt.figure(figsize=(14, 10))
sns.scatterplot(data=shop_edu_etc, x='경도', y='위도', hue='상권업종소분류명')

shop_edu_etc_computer = shop_edu_etc[shop_edu_etc['상권업종소분류명'] == '컴퓨터 학원']
shop_edu_etc_computer

 

shop_edu_etc_computer.shape

 

plt.figure(figsize=(14, 10))
sns.scatterplot(data=shop_edu_etc_computer, x='경도', y='위도', hue='상권업종소분류명')

3. Folium

Folium은 파이썬에서 대화형 지도(interactive map)를 생성할 수 있는 라이브러리입니다. 특히, 지리 데이터(Geospatial Data) 시각화에 최적화되어 있으며, 간단한 코드로 복잡한 지도 기능을 구현할 수 있도록 도와줍니다.

pip install folium

 

import folium

# 어디를 중심으로 지도를 킬 것 인가?
map_folium = folium.Map(location=[37.56652479270633, 126.9779129116262], zoom_start=15)
# folium.Popup : 마커를 클릭했을때, 나오는 팝업창
popup = folium.Popup('서울특별시청', max_width=200)
# 마커 생성
folium.Marker(location=[37.56652479270633, 126.9779129116262], popup=popup).add_to(map_folium)

popup = folium.Popup('덕수궁', max_width=200)
folium.Marker(location=[37.56585320879458, 126.97514572197248], popup=popup).add_to(map_folium)

popup = folium.Popup('서울지방경찰청', max_width=200)
folium.Marker(location=[37.57504045678939, 126.97195576938117], popup=popup).add_to(map_folium)

popup = folium.Popup('광화문', max_width=200)
folium.Marker(location=[37.57617987638928, 126.97694467807803], popup=popup).add_to(map_folium)

popup = folium.Popup('영풍문고-종로본점', max_width=200)
folium.Marker(location=[37.56999947440024, 126.98228391170936], popup=popup).add_to(map_folium)

map_folium

 

from folium.features import CustomIcon

icon = CustomIcon('icon.png', icon_size=(45, 45))

map_folium = folium.Map(location=[37.56652479270633, 126.9779129116262], zoom_start=15)
popup = folium.Popup('서울특별시청', max_width=200)
folium.Marker(location=[37.56652479270633, 126.9779129116262], popup=popup,
              icon=folium.Icon(icon='star', color='red')).add_to(map_folium)

popup = folium.Popup('덕수궁', max_width=200)
folium.Marker(location=[37.56585320879458, 126.97514572197248], popup=popup,
              icon=folium.Icon(icon='ok', color='pink')).add_to(map_folium)

popup = folium.Popup('서울지방경찰청', max_width=200)
folium.Marker(location=[37.57504045678939, 126.97195576938117], popup=popup,
              icon=icon).add_to(map_folium)

popup = folium.Popup('광화문', max_width=200)
folium.Marker(location=[37.57617987638928, 126.97694467807803], popup=popup).add_to(map_folium)

# CircleMarker(): 원의 범위를 마커로 설정
popup = folium.Popup('내땅', max_width=200)
folium.CircleMarker(location=[37.56999947440024, 126.98228391170936], popup=popup,
              radius=30, color='red', fill_color='#ec4074').add_to(map_folium)

map_folium

data = shop_edu_etc_computer

edu_map = folium.Map(location=[data['위도'].mean(), data['경도'].mean()], zoom_start=12)    
# zoom_start : 서울 전역을 봐야하기 때문에 멀리 봐야함
# 데이터의 위도&경도의 평균을 구해주면 중앙을 구할 수 있음

for i in data.index:
    edu_name = data.loc[i, '상호명'] + ' - ' + data.loc[i, '도로명주소']
    # print(edu_name)
    popup = folium.Popup(edu_name, max_width=500)
    folium.Marker(location=[data.loc[i, '위도'], data.loc[i, '경도']],
                  popup=popup).add_to(edu_map)

edu_map

 

'Python' 카테고리의 다른 글

커피 프랜차이즈의 입점전략  (3) 2025.07.22
서울시 공공자전거 실시간 대여정보  (2) 2025.07.22
Online Retail  (0) 2025.07.21
Matplotlib  (0) 2025.07.21
Pandas  (0) 2025.07.17

1. 캐글

캐글(Kaggle)은 데이터 과학자와 머신러닝 엔지니어들이 학습, 협업, 경쟁할 수 있는 온라인 플랫폼입니다. 구글에 소속된 이 플랫폼은 다양한 데이터셋과 머신러닝 문제를 제공하며, 사용자들이 자신의 모델을 개발하고 성능을 경쟁적으로 평가받을 수 있는 경진대회도 열립니다. 초보자는 데이터를 다루는 실습을 하고, 경험 많은 전문가들은 포트폴리오를 확장하거나 상금을 받을 기회를 얻을 수 있습니다. 또한, 커뮤니티 포럼과 튜토리얼, 노트북 공유를 통해 지식을 공유하고 학습할 수 있는 환경을 제공합니다. 캐글은 데이터 분석과 머신러닝을 배우고 실제 문제에 적용해 보고 싶은 사람들에게 유용한 플랫폼입니다.

 

2. Online Retail

아래 사이트에 접속해 데이터를 다운로드합니다.

https://www.kaggle.com/datasets/mashlyn/online-retail-ii-uci

 

Online Retail II UCI

A real online retail transaction data set of two years.

www.kaggle.com

 

import pandas as pd

retail = pd.read_csv('/본인의 구글드라이브 경로/online_retail_II.csv')
retail

 

retail.info()

 

'''
InvoiceNo: 주문 번호
StockCode: 상품 코드
Description: 상품 설명
Quantity: 주문 수량
InvoiceDate: 주문 날짜
Price: 상품 가격
Customer ID: 고객 아이디
Country: 고객 거주지역(국가)
'''
retail.columns

 

retail.describe()

 

len(retail)

 

# 각 컬럼당 null이 몇 개 있는지 확인
retail.isnull().sum()

 

# 각 컬럼당 null이 얼마나 있는지 비율 확인
retail.isnull().mean()

 

# 비회원/탈퇴/휴면회원 제거
retail = retail[pd.notnull(retail['Customer ID'])]
retail

 

len(retail)

 

# 구입 수량이 0 이하인 데이터를 확인
retail[retail['Quantity'] <= 0]

 

# 구입 수량이 1이상인 데이터만 저장
retail = retail[retail['Quantity'] >= 1]
len(retail)

 

# 구입 가격이 0 이하인 데이터를 확인
retail[retail['Price'] <= 0]

 

# 구입 가격이 0보다 큰 데이터만 저장
retail = retail[retail['Price'] > 0]
len(retail)

 

# 고객의 총 지출비용(CheckoutPrice) 파생변수 만들기
# 총 지출비용(CheckoutPrice) = 가격(Price) * 수량(Quantity)
# retail.loc[:, 'CheckoutPrice'] = retail['Price'] * retail['Quantity']
retail['CheckoutPrice'] = retail['Price'] * retail['Quantity']
retail

 

retail.info()

 

retail['InvoiceDate'] = pd.to_datetime(retail['InvoiceDate'])
retail.info()

 

# 전체 매출
total_revenue = retail['CheckoutPrice'].sum()
total_revenue

 

# 각 나라별 구매 횟수
pd.options.display.max_rows = 20
# value_counts(): 객체의 각 고유값(유니크 값)의 개수를 계산하고, 이를 내림차순으로 정렬해 반환하는 함수
retail['Country'].value_counts()
# retail.groupby('Country')['Quantity'].count().sort_values(ascending=False)

 

# 국가별 매출
rev_by_countries = retail.groupby('Country')['CheckoutPrice'].sum().sort_values()
rev_by_countries

 

import matplotlib.pyplot as plt

# matplotlib 객체 생성
# 그래프를 그릴 축(ax)과 그림(fig)을 생성
fig, ax = plt.subplots(figsize=(20, 10))

# 막대 그래프 그리기
ax.bar(rev_by_countries.index, rev_by_countries.values)

# 라벨 설정
ax.set_xlabel('Country', fontsize=12)
ax.set_ylabel('Revenue', fontsize=12)
ax.set_title('Revenue By Country', fontsize=15)

# x축 눈금 라벨 회전
ax.set_xticks(range(len(rev_by_countries.index)))
ax.set_xticklabels(rev_by_countries.index, rotation=45)

# 그래프 출력
# 래프와 텍스트가 잘리지 않고 보기 좋게 배치되도록 자동으로 여백을 조정하는 유용한 함수
plt.tight_layout()
plt.show()

rev_by_countries / total_revenue

 

# 월별 매출 구하기
retail['InvoiceDate'].sort_values(ascending=False)

 

def extract_month(date):
    month = str(date.month)
    if date.month < 10:
        month = '0' + month
    return str(date.year) + month

 

rev_by_month = retail.set_index('InvoiceDate').groupby(extract_month)['CheckoutPrice'].sum()
rev_by_month

 

def plot_bar(df, xlabel, ylabel, title, figsize=(20, 10), fontsize=12, titlesize=15, rotation=45):
    fig, ax = plt.subplots(figsize=figsize)
    ax.bar(df.index, df.values)
    ax.set_xlabel(xlabel, fontsize=fontsize)
    ax.set_ylabel(ylabel, fontsize=fontsize)
    ax.set_title(title, fontsize=titlesize)
    ax.set_xticks(df.index)
    ax.set_xticklabels(df.index, rotation=rotation, fontsize=fontsize)
    plt.tight_layout()
    plt.show()

 

plot_bar(rev_by_month, 'Month', 'Revenue', 'Revenue By Month')

# 요일별 매출 구하기
def extract_dow(date):
    return date.dayofweek

 

rev_by_dow = retail.set_index('InvoiceDate').groupby(lambda date: date.dayofweek)['CheckoutPrice'].sum()
rev_by_dow

 

import numpy as np

DAY_OF_WEEK = np.array(['Mon', 'Tue', 'Web', 'Thur', 'Fri', 'Sat', 'Sun'])
rev_by_dow.index = DAY_OF_WEEK[rev_by_dow.index]
rev_by_dow.index

 

rev_by_dow

 

plot_bar(rev_by_dow, 'DOW', 'Revenue', 'Revenue By DOW')

# 시간대별 매출 구하기
rev_by_hour = retail.set_index('InvoiceDate').groupby(lambda date: date.hour)['CheckoutPrice'].sum()
rev_by_hour

 

plot_bar(rev_by_hour, 'Hour', 'Revenue', 'Revenu By Hour')

1. Matplotlib

Matplotlib은 파이썬에서 데이터를 시각화하는 데 널리 사용되는 강력한 라이브러리입니다. 다양한 그래프와 차트를 그릴 수 있으며, 선 그래프, 막대 그래프, 히스토그램, 산점도 등 기본적인 그래프부터 복잡한 3D 플롯까지 지원합니다. 사용법이 비교적 간단하고, 커스터마이징이 가능하여 데이터의 패턴과 트렌드를 효과적으로 표현할 수 있습니다. 또한, NumPy와 Pandas와 같은 데이터 분석 라이브러리와 잘 통합되어 데이터 과학, 머신러닝, 통계 등 다양한 분야에서 활용됩니다. Matplotlib의 기본 모듈인 pyplot은 MATLAB과 유사한 인터페이스를 제공해 초보자도 쉽게 사용할 수 있도록 설계되었습니다.

https://matplotlib.org/

 

pip install matplotlib

 

1. 기본 구조

  • Figure: 전체 그림 (도화지)
  • Axes: 하나의 서브 그래프 (보통 x축, y축 포함)
  • Axis: x축과 y축 자체
import matplotlib.pyplot as plt

plt.plot([1, 2, 3, 4]) # 리스트의 값들은 y값들이며, x값은 자동으로 만들어줌
plt.show()

 

plt.plot([1, 2, 3, 4], [1, 2, 3, 4])
plt.show()

 

import numpy as np

data = np.arange(1, 100)
plt.plot(data)
plt.show()

data1 = np.arange(1, 50)
plt.plot(data1)
data2 = np.arange(50, 100)
plt.plot(data2)
plt.show()

선 그래프 plt.plot() 연속적인 데이터 추세
막대 그래프 plt.bar() 범주형 데이터 비교
수평 막대 plt.barh() 막대를 가로로
산점도 plt.scatter() 두 변수의 관계 시각화
히스토그램 plt.hist() 분포 시각화
파이 차트 plt.pie() 비율 표현

 

 

2. 스타일 옵션

# 한글 fonts-nanum 설치
!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf

plt.rc('font', family='NanumBarunGothic')

# 런타임에서 세션 다시 시작 및 실행 눌러야 한글 적용된다.

 

plt.figure(figsize=(4, 5)) # inch
plt.plot([1, 2, 3], [1, 2, 3])
plt.title('제목', fontsize=30)
plt.xlabel('X축', fontsize=20)
plt.ylabel('Y축', fontsize=20, rotation=0)
plt.show()

plt.figure(figsize=(15, 10))
plt.title('마커설정', fontsize=30)
plt.plot(np.arange(10), np.arange(10), color='deepskyblue', marker='o', linestyle='-.')
plt.plot(np.arange(10), np.arange(10)*2, color='deeppink', marker='v', linestyle='--')
plt.plot(np.arange(10), np.arange(10)*3, color='gold', marker='*', ms=10, linestyle='')

# 범례
# 기본 위치는 왼쪽 상단
plt.legend(['10', '10*2', '10*3'], fontsize=15, loc='lower right', ncol=3)

plt.xlim(0, 12)
plt.ylim(0, 30)

plt.xticks(rotation=30)
plt.yticks(rotation=30)

plt.savefig('my_plot.png')  # 그래프를 이미지로 저장
plt.show()

x = ['파이썬', '웹개발', '데이터분석', '머신러닝', '딥러닝', '컴퓨터비전']
y = [95, 70, 75, 60, 50, 30]
plt.figure(figsize=(8, 5))
plt.title('AI 성적표', fontsize=25)
plt.ylabel('수강생 점수')
# alpha : 투명도 
plt.bar(x, y, alpha=0.5, color='deeppink')
plt.show()

x = ['파이썬', '웹개발', '데이터분석', '머신러닝', '딥러닝', '컴퓨터비전']
y = [95, 70, 75, 60, 50, 30]
plt.figure(figsize=(8, 5))
plt.title('AI 성적표', fontsize=25)
plt.xlabel('수강생 점수')
plt.barh(x, y, alpha=0.5, color='deepskyblue')
plt.show()

import pandas as pd

x = ['파이썬', '웹개발', '데이터분석', '머신러닝', '딥러닝', '컴퓨터비전']
y = [95, 70, 75, 60, 50, 30]
# pandas 이용해서 데이터프레임으로 x축 ,y축 구분
df = pd.DataFrame({"과목":x, "점수":y})

fig, ax = plt.subplots(figsize=(5, 4))
ax.bar(df["과목"], df["점수"])
ax.set_xlabel("과목", fontsize=12)
ax.set_ylabel("점수", fontsize=12)
ax.set_title("코리아 학생 점수", fontsize=20)
ax.set_xticks(range(len(df.index)))
plt.tight_layout() # 레이아웃이 겹치지 않도록 자동으로 정리해주는 함수
plt.show()

'Python' 카테고리의 다른 글

소상공인시장진흥공단_상가정보 데이터셋  (3) 2025.07.21
Online Retail  (0) 2025.07.21
Pandas  (0) 2025.07.17
Numpy  (3) 2025.07.17
FastAPI  (0) 2025.07.17

1. 판다스(Pandas)

판다스(Pandas) 데이터 분석을 위한 파이썬 라이브러리  하나로,  형태의 데이터나 다양한 형태의 데이터를 쉽게 처리하고 분석할  있도록 도와주는 도구입니다. 주로 데이터프레임(DataFrame)이라는 자료구조를 제공하며, 이를 통해 테이블 형태의 데이터를 다루기 용이합니다.

pip install pandas

 

import pandas as pd

 

 

2. Series와 DataFrame

1. Series

Series 1차원 배열과 같은 자료구조로 하나의 열을 나타냅니다. 또한  요소는 인덱스(index) (value)으로 구성되어 있습니다. 값은 넘파이의 ndarray 기반으로 저장됩니다. Series 다양한 데이터 타입을 가질  있으며 정수, 실수, 문자열  다양한 형태의 데이터를 담을  있습니다

idx = ['김사과', '반하나', '오렌지', '이메론', '배애리']
data = [67, 75, 90, 62, 98]

# pd.Series(데이터, 인덱스, ...)
pd.Series(data)

 

se1 = pd.Series(data, idx)
se1

 

print(se1.index)
print(se1.values)
print(type(se1.values))

 

2. DataFrame

데이터프레임(DataFrame) 판다스(Pandas) 라이브러리에서 제공하는 중요하고 강력한 데이터 구조로, 2차원의 테이블 형태 데이터를 다루는  사용됩니다. 또한 각 요소는 인덱스(index), 열(column), 값(value)으로 구성되어 있습니다. 데이터프레임은 행과 열로 이루어져 있으며,  열은 다양한 데이터 타입을 가질  있습니다. 값은 넘파이의 ndarray 기반으로 저장됩니다.

data = [[67, 93, 91],
        [75, 68, 96],
        [87, 81, 82],
        [62, 70, 75],
        [98, 56, 87]]

idx = ['김사과', '반하나', '오렌지', '이메론', '배애리']
col = ['국어', '영어', '수학']

 

# pd.DataFrame(데이터, 인덱스, 컬럼, ...)
pd.DataFrame(data)
pd.DataFrame(data, idx)

 

pd.DataFrame(data, idx, col)

df = pd.DataFrame(index=idx, columns=col, data=data)
df

 

print(df.index)
print(df.columns)
print(df.values)

 

# 딕셔너리를 사용하여 데이터프레임을 생성하기
dic = {
    '국어':[67, 75, 76, 62, 98],
    '영어':[93, 68, 81, 70, 56],
    '수학':[91, 96, 82, 75, 87]
}

df = pd.DataFrame(data=dic, index=idx)
df

 

 

3. CSV 파일 읽어오기

CSV 파일은 Comma-Separated Values(쉼표로 구분된 값) 파일의 약자로, 데이터를 단순한 텍스트 형식으로 저장하는 데 사용되는 파일 형식입니다.

 

아래 파일을 다운받고 구글드라이브에 업로드합니다.

 

 

 

df = pd.read_csv('/본인 구글드라이브 경로/idol.csv')
df

 

type(df)

 

 

4. 데이터프레임 기본 정보 알아보기

df.info()

 

df.columns

 

new_columns = ['name', 'group', 'company', 'gender', 'birthday', 'height', 'blood', 'brand']
df.columns = new_columns
df

 

# describe(): 통계 정보를 반환
df.describe()

 

df.describe(include=object) # Top: 최빈값, freq: 최빈값의 빈도

 

# 원하는 개수의 데이터 보기
df.head() # 상위 5개의 row를 출력

 

df.head(3) # 상위 3개의 row를 출력

 

df.tail() # 하위 5개의 row를 출력

 

df.tail(2) # 하위 2개의 row를 출력

 

# 정렬하기
df.sort_index() # index로 오름차순 정렬: 기본값

 

df.sort_index(ascending=False) # index로 내림차순 정렬

 

df.sort_values(by='height') # 키로 오름차순 정렬

 

df.sort_values(by='height', ascending=False) # 키로 내림차순 정렬

 

df.sort_values(by='height', ascending=False, na_position='first') # 키로 내림차순 정렬. NaN을 위로 올림

 

# 1차 정렬: 키(내림차순), 2차 정렬: 브랜드(내림차순)
df.sort_values(by=['height', 'brand'], ascending=[False, False], na_position='first')

 

 

5. 데이터 다루기

df.head()

 

df['blood']

 

type(df['blood'])

 

df.blood

 

df.head(3)

 

df[:3]

 

# loc 인덱싱: 컬럼 인덱싱
df.loc[:, 'name'] # df['name']

 

df.loc[2:5, 'name'] # 5번을 포함

 

df.loc[2:5, ['name', 'gender', 'height']]

 

df.loc[[2,5], ['name', 'gender', 'height']]

 

df.loc[2:5, 'name':'gender']

 

#indexlocation 인덱싱 : index로 인덱싱, 끝점은 포함하지 않음
df.iloc[:,0]

 

df.iloc[:, 0:3] # 3을 포함하지 않음

 

df.iloc[:, [0, 3]]

 

df.iloc[1:5, 0:2]

 

df['height'] >= 180

 

df[df['height'] >= 180]

 

df[df['height'] >= 180]['name'] # df['name'][df['height'] >= 180]

 

df[df['height'] >= 180][['name', 'gender', 'height']]

 

df[df['height']>180][['name','gender','height']]    
# 여러개가 되면 해당문법에서 대괄호를 하나 더 감싸줘야 한다.

 

df

 

company = ['빅히트','어도어']
df['company'].isin(company)     
# company 변수를 만들고 isin 메소드를 써서 company 시리즈에서 위에 값이 포함되는지를 boolean으로 출력

 

df[df['company'].isin(company)] # df.loc[df['company'].isin(company),:]
# 변수처리된 company를 넣어서 빅히트와 어도어 value를 가진 index만 추출

 

 

6. 결측값

결측값은 값이 누락된 데이터를 의미하며, 판다스에서는 일반적으로 NaN으로 표시됩니다.

df.info()

 

df

 

df.isna()

 

df.isnull()

 

df.notnull()

 

df['height'].isna()
# height 열 전체를 불러옴

 

df[df['height'].isna()]
# 키가 들어가있지 않은 사람에 대한 index만을 뽑아줌

 

df[df['height'].isna()]['name']

 

df[df['height'].notnull()]
# null값이 들어간 행을 제외하고 전체를 불러옴

 

df[~df['height'].isnull()]
# null값이 들어간 행을 제외하고 전체를 불러옴

 

df.loc[df['company'].notnull(), ['name', 'company', 'group', 'gender']]

 

df['height']

 

# fillna() : 결측값을 채워주는 함수
df['height'].fillna(0)  # df['height].fillna(0,inplace=True) 적용
# 단 키가 0이 된다는건 말도안되니까 결측치 채울 때, 잘 생각해야함

 

df['height']

 

df_copy = df.copy()
df_copy

 

height = df_copy['height'].mean()
height
# 평균치 변수 선언

 

# 위에서 선언한 height변수를 결측치에 넣음 즉, 결측치에 평균값을 넣음
df_copy['height'] = df_copy['height'].fillna(height)
df_copy['height']

 

# 다시 NaN으로 출력
df_copy = df.copy()
df_copy['height']

 

height = df_copy['height'].median() # 50%값, 중위
height

 

df_copy['height'].fillna(height, inplace=True)  
# 변수로 덮지않고 inplace = True로 덮을 수 있음
df_copy['height']

 

df_copy = df.copy()
df_copy

 

# dropna(): 결측값이 있는 행 또는 열을 제거. 결측값이 한개라도 있는 경우 삭제
# axis=0 (행 삭제)
df_copy.dropna()

 

df_copy.dropna(axis=1) # 결측값이 있는 열을 제거
# 단, 추천하지 않음 카테고리 전체가 사라지는거라 위험도가 높음

 

 

※ axis

1. NumPy는 수학적 배열 연산에서 출발했기 때문에, 축(axis) 개념이 배열의 모양과 연산 방향에 초점을 맞춥니다.

- axis=0: 배열의 세로 방향(열), axis=1: 배열의 가로 방향(행)

 

2. Pandas는 데이터 분석에 특화된 라이브러리로, 행(row)과 열(column)을 명시적으로 구분하여 작업을 수행합니다.

- axis=0: 행(row)을 대상으로 작업(열 간 연산). axis=1: 열(column)을 대상으로 작업(행 간 연산)

 

 

7. 행, 열 추가 및 삭제하기

df_copy = df.copy()
df_copy

 

dic = {
    'name': '김사과',
    'group': '과수원',
    'company': '애플',
    'gender': '여자',
    'birthday': '2000-01-01',
    'height': 160.0,
    'blood': 'A',
    'brand': 1234567
}

 

# concat(): 데이터를 합침. axis=0 (기본값)
df_copy = pd.concat([df_copy, pd.DataFrame(dic, index=[0])], ignore_index=True)
df_copy

 

df_copy['nation'] = '대한민국'
df_copy.head()

 

df_copy.tail()

 

df_copy.loc[df_copy['name'] == '김사과', 'nation'] = '미국'
df_copy.tail()

 

# 행 제거하기
df_copy.drop(20, axis=0) # 0: 행, 1: 열

 

df_copy.tail()

 

df_copy.drop([1, 3, 5, 7, 20], axis=0)

 

# 열 제거하기
df_copy.drop('nation', axis=1)

 

df_copy.drop(['nation', 'group'], axis=1)

 

 

8. 통계 함수

df_copy.describe()

 

df_copy['height'].sum() # 합계

 

df_copy['height'].count() # 개수, NaN은 포함하지 않음

 

df_copy['height'].mean() # 평균

 

df_copy['height'].median() # 중앙값

 

※ 평균과 중앙값

평균은 모든 데이터를 더한 후, 데이터 개수로 나눈 값입니다. 데이터를 고르게 분배했을 때, 한 데이터가 가질 수 있는 이론적인 중심값을 의미합니다. 중앙값은 데이터를 크기 순서대로 정렬했을 때, 가운데 위치하는 값입니다. 데이터의 순서에만 영향을 받고, 값의 크기에는 영향을 받지 않습니다. 데이터가 고르게 분포된 경우 평균과 중앙값이 비슷하거나 같습니다. 하지만 데이터에 극단값(Outlier)이 있는 경우 평균은 극단값의 영향을 받아 왜곡될 수 있지만, 중앙값은 비교적 안정적입니다.

 

df_copy['height'].max() # 최대값

 

df_copy['height'].min() # 최소값

 

df_copy['height'].var() # 분산

 

df_copy['height'].std() # 표준편차

 

※ 분산과 표준편차

분산(Variance)과 표준편차(Standard Deviation)는 데이터가 평균에서 얼마나 퍼져 있는지를 나타내는 산포도(분포 정도)를 측정하는 지표입니다. 분산은 데이터가 평균을 기준으로 얼마나 퍼져 있는지를 나타냅니다. 평균에서 각 데이터의 거리를 제곱한 값들의 평균입니다. 표준편차는 분산의 제곱근입니다. 분산은 제곱 값이기 때문에 단위가 커질 수 있는데, 이를 원래 데이터와 같은 단위로 변환하기 위해 제곱근을 씌웁니다.

 

 

 

 

 

9. 그룹

df_copy

 

# groupby(): 데이터를 그룹으로 묶어 분석할 때 사용
df_copy.groupby('group')

 

# 그룹을 맺으면 통계함수를 사용할 수 있음
df_copy.groupby('group').count()

 

df_copy.groupby('group').mean(numeric_only=True)
# df_copy.groupby('group').mean() -> 하면 에러남!
# numeric_only = True -> 숫자에 대한 평균만 내겠다고 처리해줘야함

 

df_copy.groupby('group').sum(numeric_only=True)

 

df_copy.groupby('gender').mean(numeric_only=True)

 

df_copy.groupby(['blood','gender']).mean(numeric_only=True)

 

df_copy.groupby(['blood','gender'])['height'].mean()

 

 

10. 중복값 제거하기

df_copy['blood']

 

# drop_duplicates(): 중복된 데이터를 제거
df_copy['blood'].drop_duplicates()

 

df_copy['blood'].drop_duplicates(keep='last')
# keep = 'last' -> 마지막 인덱스 추출

 

# value_counts(): 열의 각 값에 대한 데이터의 개수를 반환. 기본은 NaN을 생략
df_copy['blood'].value_counts()

 

df_copy['company'].value_counts()

 

df_copy['company'].value_counts(dropna=False) # NaN를 포함

 

 

11. 데이터프레임 합치기

 

아래 파일을 다운받고 추가로 구글드라이브에 업로드합니다.

idol2.csv
0.00MB

 

 

 

df1 = pd.read_csv('/본인 구글드라이브 경로/idol.csv')
df2 = pd.read_csv('/본인 구글드라이브 경로/idol2.csv')

 

df1

 

df2

 

df_copy = df1.copy()

 

pd.concat([df1, df_copy]) # axis=0 (기본값)

 

df_concat = pd.concat([df1, df_copy])

# reset_index(): index를 새롭게 적용
# drop=True 옵션을 사용하여 기존 index가 컬럼으로 만들어지는 것을 방지
df_concat.reset_index(drop=True)

 

pd.concat([df1, df2], axis=1) # 같은 index와 결합

 

df3 = df2.drop([1, 3, 5, 7, 9])
df3

 

pd.concat([df1, df3], axis=1)

 

df_right = df2.drop([1, 3, 5, 7, 9], axis=0)
df_right

 

df_right = df_right.reset_index(drop=True)
df_right

 

dic = {
    '이름': '김사과',
    '연봉': 9000,
    '가족수': 10
}

 

df_right = pd.concat([df_right, pd.DataFrame(dic, index=[0])], ignore_index=True)
df_right

 

pd.concat([df1, df_right], axis=1)

 

# merge(): 특정 고유한 키(unique, id)값을 기준으로 합침
# merge(데이터프레임1, 데이터프레임2, on='유니크값', how='병합의 기준')
# 병합의 기준: left, right, inner, cross
pd.merge(df1, df_right, on='이름', how='left')

 

pd.merge(df1, df_right, on='이름', how='right')

 

pd.merge(df1, df_right, on='이름', how='inner')     # 양쪽 둘 다 있는것만 합쳐짐

 

pd.merge(df1, df_right, how='cross')
# 이름 x와 이름 y 대응되는것 모두 포함

 

df_right.columns = ['성함', '연봉', '가족수']       # y이름 컬럼명을 성함으로 바꿈
df_right

 

# pd.merge(df1, df_right, on='이름', how='inner') KeyError: '이름'
pd.merge(df1, df_right, left_on='이름', right_on='성함', how='inner')

 

 

12. 등수 매기기

# rank(): 데이터프레임 또는 시리즈의 순위를 매기는 함수. 기본값은 ascending
df1['브랜드순위'] = df1['브랜드평판지수'].rank()    # 브랜드 순위 -> 없는 컬럼명 , 없으면 만드는 것!
# 컬럼명을 변수라고 부를 수 있는데, 파생변수라고 부름
df1
# 기본값이 ascending이기때문에 제일 높은게 rank가 제일 낮게 나옴

 

df1['브랜드순위'] = df1['브랜드평판지수'].rank(ascending=False)
df1

 

# astype(): 특정열의 자료형을 변경
df1['브랜드순위'] = df1['브랜드순위'].astype(int)
df1

 

df1['브랜드순위'].dtypes

 

 

13. 날짜타입 사용하기

df_copy = df.copy()
df_copy

 

df_copy.info()

 

df_copy['birthday']

 

# to_datatime(): object타입에서 datetime타입으로 변환
df_copy['birthday'] = pd.to_datetime(df_copy['birthday'])
print(type(df_copy['birthday']))
print(df_copy['birthday'].dtypes)

 

df_copy.info()

 

df_copy['birthday'].dt.year

 

df_copy['birthday'].dt.month

 

df_copy['birthday'].dt.day

 

df_copy['birthday'].dt.hour

 

df_copy['birthday'].dt.minute

 

df_copy['birthday'].dt.second

 

df_copy['birthday'].dt.dayofweek # 요일: 0(월요일) ~ 6(일요일)

 

df_copy['birthday'].dt.isocalendar().week

 

 

14. apply 사용하기

Pandas의 apply() 함수는 데이터프레임이나 시리즈의 데이터를 사용자 정의 함수 또는 내장 함수에 적용하여 새로운 값을 계산하거나 변환할 때 사용됩니다. 데이터를 행(row) 또는 열(column) 단위로 처리할 수 있는 강력한 도구입니다.

df_copy = df.copy()
df_copy
df_copy.head()

 

# 라벨 인코딩
# 성별을 남자는 1, 여자는 0으로 변환(loc를 사용)
df_copy.loc[df_copy['gender'] == '남자', 'gender'] = 1
df_copy.loc[df_copy['gender'] == '여자', 'gender'] = 0

 

df_copy.head()

 

df_copy = df.copy()
df_copy

 

def male_or_female(x):
    if x == '남자':
        return 1
    elif x == '여자':
        return 0
    else:
        return None

 

print(male_or_female('남자'))
print(male_or_female('여자'))

 

df_copy['gender'].apply(male_or_female)
# 위에 male_or_female 함수를 콜백함수로 불러와서 apply 시킴

 

df_copy['gender'].apply(lambda x: 1 if x == '남자' else 0)
# 익명함수 lambda를 사용해서 메모리 차지 낮춤

 

df_copy['NewGender'] = df_copy['gender'].apply(lambda x: 1 if x == '남자' else 0)
df_copy.head()

# 새로운 파생변수 생성

 

 

15. map 사용하기

Pandas의 map() 함수는 Series 객체에서 사용할 수 있는 함수로, 각 요소에 대해 함수나 매핑 규칙을 적용하여 새로운 값을 계산하거나 변환할 때 사용됩니다. map()은 데이터의 각 요소를 순회하며 특정 작업을 수행하므로, 데이터를 가공하거나 변환하는 데 유용합니다.

df_copy = df.copy()
df_copy

 

map_gender = {'남자':1, '여자':0}

 

df_copy['gender'].map(map_gender)

 

df_copy['NewGender'] = df_copy['gender'].map(map_gender)
df_copy.head()

 

 

16. 데이터프레임의 산술연산

df1 = pd.DataFrame({
    '파이썬':[60, 70, 80, 90, 95],
    '데이터분석':[40, 60, 70, 55, 87],
    '머신러닝딥러닝':[35, 40, 30, 70, 55]
})

 

df1

 

df1['파이썬'].dtypes

 

type(df1['파이썬'])

 

df1['파이썬'] + df1['데이터분석'] + df1['머신러닝딥러닝']

 

# df1에 총점, 평균이라는 파생변수를 만들고 파생변수에 총점, 평균을 구해서 저장
df1['총점'] = df1['파이썬'] + df1['데이터분석'] + df1['머신러닝딥러닝']
df1['평균'] = df1['총점'] / 3
df1

 

df1['파이썬'].sum() # df1['파이썬'].sum(axis=0)

 

df1['파이썬'].mean()

 

df1.sum()

 

df1.mean()

 

df1 = pd.DataFrame({
    '파이썬':[60, 70, 80, 90, 95],
    '데이터분석':[40, 60, 70, 55, 87],
    '머신러닝딥러닝':[35, 40, 30, 70, 55]
})

df2 = pd.DataFrame({
    '파이썬':['C', 'B', 'B', 'A', 'A'],
    '데이터분석':[40, 60, 70, 55, 87],
    '머신러닝딥러닝':[35, 40, 30, 70, 55]
})

 

# df1 + df2 # TypeError: unsupported operand type(s) for +: 'int' and 'str'
df1 + 10
# df2 + 10 # TypeError: can only concatenate str (not "int") to str

 

df1 = pd.DataFrame({
    '데이터분석':[40, 60, 70, 55, 87],
    '머신러닝딥러닝':[35, 40, 30, 70, 55]
})

df2 = pd.DataFrame({
    '데이터분석':[40, 60, 70, 55],
    '머신러닝딥러닝':[35, 40, 30, 70]
})

 

df1 + df2 # 행의 갯수가 다를 경우 빠진 데이터를 NaN으로 취급하기 때문에 결과는 NaN

 

 

17. select_dtypes

df_copy = df.copy()
df_copy

 

df.info()

 

df.select_dtypes(include='object') # 문자열 컬럼만 가져오기

 

df.select_dtypes(exclude='object') # 문자열 컬럼만 빼고 가져오기

 

# 문자가 아닌 컬럼에만 10을 더함
df.select_dtypes(exclude='object') + 10

 

# 문자열을 가지고 있는 컬럼의 이름만 변수에 저장하여 출력
str_cols = df.select_dtypes(include='object').columns
str_cols

 

df[str_cols]

 

 

18. get_dummies

get_dummies()는 Pandas에서 범주형 데이터를 원-핫 인코딩(one-hot encoding) 방식으로 변환하는 데 사용됩니다.

 

원-핫 인코딩

원-핫 인코딩은 각 범주를 별도의 열로 변환하고, 해당 범주에 해당하는 곳에 1을, 나머지에는 0을 채우는 방식입니다. 예를 들어, 데이터가 "Red", "Green", "Blue"와 같은 문자열이라면, 모델은 이를 이해하지 못합니다. 범주형 데이터를 숫자로 변환해야 모델이 계산할 수 있습니다. 원-핫 인코딩은 범주형 데이터를 숫자로 변환하면서도 각 범주 간의 순서나 크기를 부여하지 않습니다.

blood_map = {'A':0, 'B':1, 'AB':2, 'O':3}
df['Blood_code'] = df['blood'].map(blood_map) # 라벨 인코딩
df.head()

 

pd.get_dummies(df['blood'])

 

df = pd.get_dummies(df, columns=['blood'])
df

 

df.info()

'Python' 카테고리의 다른 글

Online Retail  (0) 2025.07.21
Matplotlib  (0) 2025.07.21
Numpy  (3) 2025.07.17
FastAPI  (0) 2025.07.17
chatGPT openAPI  (0) 2025.07.16

+ Recent posts