예제로 익히는 Python - 3회차

Suhyeon Lee·2024년 10월 25일
0

Python 자료형

(1) 기본 자료형

  • number
    • 정수와 실수
    • a=1234
  • string
    • 문자열
    • str1 = 'hi'
  • boolean
    • 참(true)/거짓(false)
    • a = True

(2) 컬렉션 자료형

  • list
    • 대괄호[]로 정의
    • 수정 가능
    • 순서 있음
    • list1 = [1, 2]
  • tuple
    • 소괄호()로 정의
    • 수정 불가
    • 순서 있음
    • tuple1 = (1, 2)
  • dictionary
    • 중괄호{}로 정의
    • key값과 value값으로 나뉨
    • 수정 가능
    • 순서 없음
    • dic = {"name": "Jane", "age": 22, "grade": "A"}
  • set
    • 중괄호{}로 정의
      • dictionary 안에 속해 있는 친구임
    • 순서 없음
    • s = {1, 2, 3}

(3) 라이브러리, 함수 자료형

  • ndarray
    • Numpy에서 배열을 나타내는 자료형
  • Series, DataFrame
    • Pandas에서 사용하는 자료형
    • Series
      • 1차원 배열
      • 일종의 리스트 형태
      • 정수, 문자열, 실수 등을 포함
    • DataFrame
      • 2차원 배열
      • 여러 개의 Series로 구성
      • 서로 다른 데이터타입을 컬럼으로 가질 수 있음
      • csv 파일 가지고 오면 DataFrame임

1. Join, Merge, Concat, Append 의 이해

1-1. 라이브러리 import

import pandas as pd 
import numpy as np
import time # 시간에 대한 모듈을 넣고 싶을 때
from PIL import Image # 사진 넣고 싶을 때

1-2. CSV 파일을 통한 테이블 LOAD

# pandas 라이브러리를 활용한 csv 파일 읽기 
df = pd.read_csv("product_details.csv") # product_details.csv
df2 = pd.read_csv("customer_details.csv") # customer_details.csv
df3 = pd.read_csv("E-commerece sales data 2024.csv") # E-commerece sales data 2024.csv
  • === 헷갈리지 마세요
    • =: 가져와서 담는다
    • ==: 같다

1-3. Merge ★★★

  • merge 함수는 공통컬럼의 이름이 달라도, 같아도 사용 가능
    • df2의 Customer_id가 df3의 user_id와 같은 의미를 가지고 있음
# 컬럼명이 같은 경우의 예시를 보여주기 위해 컬럼명을 임의로 변경
df3['Customer ID']=df3['user id']
  • df3['Customer ID']=df3['user id']
    • 기존에 있는 'user id'를 가져와서 새로운 이름의 컬럼으로 추가
  • rename해서 merge해도 되지만 매번 하기 귀찮으니까 left_on, right_on 활용법 알아두면 좋음
# 컬럼명이 같을 경우, 아래와 같이 구현할 수 있습니다. 
# 디폴트값은 inner join 입니다.공통컬럼값이 합쳐져 하나의 컬럼으로 출력됩니다. 
merge_df = pd.merge(df2,df3)


#위 코드와 동일한 기능입니다. on 절을 사용할 수 있어요. 
merge_df = pd.merge(df2,df3, how='inner', on='Customer ID')
# 데이터프레임 객체의 차원 형태(레이블 정보)를 튜플 형식으로 반환
# (예) 3행 2열 객체 → (3, 2)
df2.shape, df3.shape
  • 실행 결과: ((3900, 18), (3294, 6))
# merge 결과 확인
marge_df

  • 공통 컬럼값 기준으로 두 데이터프레임이 합쳐짐(17+5+1=23)
  • Q. merge 전후의 row수가 다르면 제대로 merge가 됐는지 어떻게 확신할 수 있나요?
    • A. groupby 하면서 확인 가능합니다.
# 기준열 이름이 다를 때
merge_df = pd.merge(df2,df3, how='inner', left_on = 'Customer ID', right_on = 'user id')

1-4. Join ★★

# 아래 데이터프레임에서의 index는 0,1,2,3 ... 을 의미 
# 단순 조인
# 이름이 겹치는 컬럼이 없을 때
# 축을 기준으로 합집합
df.join(df3)

# join 방식 설정
df.join(df3, how='right')

# join 시 이름이 같은 컬럼이 있을 경우, 옵션으로 설정하여 조인 가능
# df.join(df2) << 오류가 남 → Category 컬럼명 중복이기 때문
df.join(df2,how='left', lsuffix='1', rsuffix='2')

# join 이후, 인덱스 정렬하기
df.join(df2,how='left', lsuffix='1', rsuffix='2', sort=True)
  • 이름이 같은 컬럼이 있으면 에러가 나요!
    • lsuffix=, rsuffix= 옵션을 넣어 해결
      • 이름은 아무거나 넣어도 됨

1-5. Concat ★★★

# 디폴트 값: 수직결합
# axis=1 수평 / axis=0 수직
#ignore_index=True : 인덱스 재배열
#join='inner' : null값(행과 열 등이 맞지 않아 생기는 NaN)을 제외한 교집합
pd.concat([df2, df3])
df3

#데이터프레임의 물리적 결합
#pd.concat([df1, df2], axis=0, ignore_index=True, join='inner')
#
#axis=0(디폴트) : 행, 밑으로 붙임
#axis=1 : 열, 오른쪽으로 붙임
#ignore_index=True : 인덱스 재배열
#join='inner' : null값(행과 열 등이 맞지 않아 생기는 NaN)을 제외한 교집합

# 세로로 결합
# Inner join
pd.concat([df2, df3], axis=0, ignore_index=True, join='inner')

# 가로로 결합
pd.concat([df2, df3], axis=1, ignore_index=True, join='inner')
  • 대괄호 쓰는 게 규칙
  • concat으로 merge 가능하지만 굳이?
    • merge의 coverage가 커서

1-6. APPEND

# 단순 결합, 없는 건 NaN으로 처리되고 결합
# df2 가 df 의 아래로 붙음
df.append(df2)
  • 제보: 곧 없어질 예정이라고 함
    • concat으로 실행하시오
  • Q. try / except로 error 말고 warning도 해결할 수 있나요?
    • A. 가능한데 warnings import해서 끄는 게 더 편해요

라이브러리가 계속 업데이트되면서 해당 기능이 없어질 예정으로 아래와 같이 concat으로 변경하여 실행해주시면 됩니다.
df.concat([df, df2])
에러가 아닌 경고메시지로, 이를 무시하고 싶다면 아래와 같은 코드를 입력해주시면 됩니다.

import warnings
warnings.fillterwarnings('ignore')

2. Pivot Table 구현

df2

# age 라는 축을 기준으로 카테고리별 고객id 카운트 
pd.pivot_table(df2, index='Age', columns='Category', values='Customer ID', aggfunc='count')

# age, Category 라는 축을 기준으로 성별 Previous Purchases 최소, 최대값 구하기 
pd.pivot_table(df2, index=['Age','Category'],columns='Gender', values='Previous Purchases', aggfunc=['min','max']).plot(kind='bar')

# 성별을 축으로 하고, 사이즈, 나이별 고객id 고유하게 카운트 
pd.pivot_table(df2, index=['Gender'],columns=['Size','Age'], values='Customer ID', aggfunc='nunique')
  • Category 안에 있던 원소가 각각의 컬럼으로 지정됨
  • aggfunc은 aggregate function의 약자
    • 통계적 가설 검정을 위해 꼭 필요하니 잘 익혀두기
    • aggfunc 인자를 생략하면 디폴트 값으로 mean 함수가 사용됨

pd.pivot_table(df2, index=['Age','Category'],columns='Gender', values='Previous Purchases', aggfunc=['min','max', 'mean','median'])

  • 여러 값을 한꺼번에 볼 수 있다!
  • 중앙값은 분포를 알 수 있으니 꼭 확인하는 게 좋음
  • mode(): 최빈값 찾는 함수

3. 그 외 유용한 메서드 소개

3-1. lambda

#lambda 함수를 이용한 홀수 출력하기 
mylist = [1, 2, 3, 4, 5]
mylist2 = list(filter(lambda x: x % 2 == 1, mylist))
mylist2

#lambda 함수를 이용한 정렬
mylist = ['apple', 'banana', 'cherrycherry','kiwi','orange','watermellon']
mylist2 = sorted(mylist, key=lambda x: len(x))
mylist2
  • sorted는 파이썬 내장 함수
    • filter랑 같아요

3-2. split

# 예시 문자열 선언 
s = "aa.bb.cc.dd.ee.ff.gg"

# '.' 구분자를 기준으로 데이터를 나눔 
# 아래 두 코드 결과 동일 
s.split('.')
s.split(sep='.')

# '.' 구분자를 기준으로 데이터를 나누고 컬럼으로 받음 
# lambda 함수와 결합하여 사용하는 경우 
df2['x']="aa.bb.cc.dd.ee.ff.gg"
# split 이해하기 - 단일 문자열
st="aa.bb.cc.dd.ee.ff.gg"

# split 이해하기 - 단일 문자열
st.split('.')

# split 이해하기 - 단일 문자열
st.split('.')[6]

# split 이해하기 - Series 
# [] 슬라이싱 기능
df2['x']

df2['Location'][1]

# split 이해하기 - Series 
df2['x'][0].split('.')[6]

# split 이해하기 - Series 
len(df2['x'][0].split('.'))

# 7번 반복, a 를 컬럼 구분자로 받아주고, format 함수를 통해 a0, a1, a2 ... 로 표기
# lambda 함수를 통해 '.' 로 구분. 단, len(x.split('.') 즉 7 보다 i 가 작을 때 수행
for i in range(7):
    df2["c{}".format(i)] = df2['x'].apply(lambda x: x.split('.')[i] if len(x.split('.'))>i else None)

for i in range(7):
    df2["명수{}".format(i)] = df2['x'].apply(lambda x: x.split('.')[i] if len(x.split('.'))>i else None)

  • .apply: 일괄 적용하고 싶을 때 사용

    • '무엇을' 일괄 적용? → lambda
  • 보통 apply와 lambda를 세트로 사용: '계산'해서 '적용'하기

  • df2['x'].apply(lambda x: x.split('.')[i] if len(x.split('.'))>i else None)

    • df2['x'].apply(lambda x: 결과값 if 7>i else None)의 뜻
    • "inline(one-line) if statement"
      - inline if 결과값 조건
      - 특징: elif 쓸 수 없음
      - def plus(a, g):
      if
      return
      대신 쓰는 것
  • Q. 컬럼명을 네이밍해줄 때 d 뒤에 중괄호 쓰는(d{}) 이유?

    • A. 문법(규칙)입니다~

3-3. rrule

df3['Time stamp'] 

# 라이브러리 불러오기
from datetime import datetime
from dateutil.rrule import rrule, DAILY

# 시작 날짜, 종료날짜
start_date = datetime(2023, 2, 1)
end_date = datetime(2023, 3, 1)

# 2023-02-01 부터 2023-03-01 까지 strf 사용하여 원하는 데이터 형식으로 출력.
daily_rule = rrule(DAILY, dtstart=datetime(2023, 2, 1), until=datetime(2023, 3, 1))

# 생성된 날짜 출력
for date in daily_rule:
    print(date.strftime('%Y-%m-%d'))
  • 시간에 대한 라이브러리

3-4. 데이터프레임에서 특정 날짜기간에 해당하는 데이터만 슬라이싱

# 2023-02-01 부터 2023-03-01 까지 strf 사용하여 원하는 데이터 형식으로 출력.
weekly_rule = rrule(DAILY, dtstart=start_date, until=end_date)
# 빈 리스트 생성 후 날짜를 담아주기
a=[]
for date in weekly_rule:
    a.append(date.strftime('%Y-%m-%d'))
a

# df3 에 있는 날짜 데이터는 string 
# string -> datetimd -> string 의 형태로 변환
# 위에서 받은 리스트에 해당하는 데이터만 필터링하기 위함 
df3['Time stamp2'] = pd.to_datetime(df3['Time stamp']).dt.strftime('%Y-%m-%d')

mask =(df3['Time stamp2'].isin(a))

df3[mask]

profile
2 B R 0 2 B

0개의 댓글