관리 메뉴

ilovechoonsik

[STARTERS 4기 TIL] 파이썬 전처리 베이스 (230208) 본문

STARTERS 4기 🚉/TIL 👶🏻

[STARTERS 4기 TIL] 파이썬 전처리 베이스 (230208)

춘시기좋아 2023. 2. 8. 09:38

 

📖 오늘 내가 배운 것

 

1. loc, iloc 사용한 데이터 추출

데이터 프레임에서 원하는 데이터 추출을 도와주는 고마운 녀석들

두 녀석의 가장 큰 차이점은 loc은 이름을 통한 추출, iloc은 번호(순서)를 통한 추출

헷갈릴 수 있으니 같이 정리

 

1.1 행 데이터 추출

loc iloc
df.loc[인덱스] 시리즈 형태로 추출 df.iloc[행번호] 시리즈 형태로 추출
df.loc[인덱스리스트]  데이터프레임 형태로 추출 df.iloc[행번호리스트] 데이터프레임 형태로 추출
df.loc[인덱스명슬라이스] 행 전체 추출, 슬라이스 시에도 인덱스 이름 사용해야 함 df.iloc[행번호슬라이스] 슬라이스로 범위 지정 추출
# 인덱스가 i1,i3,i5인 행 추출
df.loc[['i1','i3','i5']]

# 인덱스가 i3인 행을 데이터프레임 형태로 추출
df.loc[['i3']]

# 인덱스가 i3인 행 이후의 모든 행 추출
df.loc['i3':]
# 짝수 행번호의 데이터 추출
df.iloc[::2]


# 홀수 행번호의 데이터 추출
df.iloc[1::2]


# 1,3,5행 슬라이스
df.iloc[1:6:2]

# 마지막 2개 행 추출하기(리스트)
df.iloc[[-2,-1]]

 

1.2 행, 열 데이터 추출

행 데이터 추출에서 사용했던 기법을 ,로 구분시켜 컬럼에 대해서도 사용가능
loc[인덱스명, 컬럼명] (리스트 및 슬라이싱도 가능)

iloc[인덱스 번호, 컬럼 번호] (리스트 및 슬라이싱도 가능)

loc iloc
# 인덱스 i1의 kor점수
df.loc['i1','kor']

# 인덱스 i1,i3,i5의 name, kor
df.loc[['i1','i3','i5'],['name', 'kor']]

# 모든 행에서 'name','math' 가져오기
df.loc[:,['name','math']]

# 인덱스 i7 이후의 행에서 'name' 가져오기(데이터프레임)
df.loc['i7':,['name']]

# 0번째 행, 0번째 열
df.iloc[0,0]

# 1,3,4번째 행 name, eng
df.iloc[[1,3,4],[0,2]]

# 1,3,5번째 행 0,2번째 열 슬라이싱
df.iloc[1:6:2, :3:2]

# 마지막행 1,3열 슬라이싱
df.iloc[-1,1:4:2]

# 모든행, 1,2열 
df.iloc[:,[1,2]]

 

2. 간단 시각화

2.1 3가지 그래프 간단하게 그려보기

import pandas as pd
import matplotlib.pyplot as plt

x = ['a','b','c','d','e']
y = [1,3,2,10,7]

# 순서대로 산점도, 막대, 선 그래프
plt.scatter(x,y,label='scatter')
plt.bar(x,y,label='bar') 
plt.plot(x,y,label='plot')

# 제목 설정
plt.title('Test Graph', size=15)

# x,y축 라벨 설정
plt.xlabel('x')
plt.ylabel('y')

# 범례 표현 (그래프 함수 안에서 label=''로 설정)
plt.legend()

# 메시지 없이 그래프 표현
plt.show()

 

2.2 원하는 데이터를 막대그래프로 표현해 보기

import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('data/scores.csv')
df.head()

x = df['name']
y = df['kor']
plt.bar(x,y)

# x축 이름들 겹치지 않게 각도 설정
plt.xticks(rotation=90)
plt.title('Scores', size=20)
plt.xlabel('name')
plt.ylabel('kor_score')
plt.show()

좌측 df의 name, kor => 우측 그래프의 x, y

 

3. 열과 행 추가/삭제/변경

3.1 열

표로 열과 행이 각각 어떤 경우에 어떤 함수 쓰는지 정리 -> append, rename, drop

  사용법 예시
열 추가 df[column] = 추가할데이터
# 컬럼이 존재하면 추가, 존재하지 않으면 수정된다.
# 학생 번호 추가하기 (1부터 시작하여 1씩 증가)
df['no'] = range(1,len(df)+1)
열 수정 df[column] = 수정할데이터 # 학생 번호 수정하기 (100부터 시작하여 1씩 증가)
df['no']  = df['no']+99
열 삭제 df.drop(columns=삭제할컬럼리스트, inplace=True)
# 존재하지 않는 열은 삭제할 수 없다.
# no, sum column 삭제
df.drop(columns=['no','sum'], inplace=True)
컬럼명 한번에 수정 df.columns = 컬럼명리스트
# 컬럼명리스트의 항목 수는 컬럼 수와 동일해야한다.
#'이름','국어','영어','수학'
df.columns=['이름','국어','영어','수학']
특정 컬렴명만 수정 df.rename(columns={'현재컬럼명1':'바꿀컬럼명1','현재컬럼명2':'바꿀컬럼명2',...}) # 이름-->성명
df = df.rename(columns={'이름':'성명'})

 

 

3.2 행

  사용법 예시
행 추가 후 인덱스 재지정 df.append(추가할데이터, ignore_index=True)
# 추가할 데이터는 딕셔너리 형태로 전달 : {컬럼1:값1, 컬럼2:값2,...}
# 데이터프레임의 끝에 행 추가
# 기존 인덱스는 무시하고, 인덱스가 새롭게 생성된다.
new_value = {'name':'Python','kor':80,'eng':90,'math':100}
df = df.append(new_value,  ignore_index=True)

# ignore_index=True 기존 인덱스 무시하고 새로 생성하겠다는 뜻
인덱스 지정하여 추가/수정 df.loc[인덱스] = 추가할데이터
df.loc[인덱스] = 수정할데이터
# 인덱스가 존재하면 해당 인덱스의 데이터가 수정된다.
# 인덱스가 존재하지 않으면 데이터프레임의 끝에 데이터가 추가된다.
# 인덱스 35에 추가
df.loc[35] = ['aaa',70,80,90]

# 인덱스 30에 추
df.loc[30] = ['ccc',60,70,80]
행 삭제 df.drop(index=[삭제할인덱스리스트], inplace=True) # 30,34,35 삭제
df.drop(index=[30,34,35], inplace=True)
전체 인덱스명 변경 df.index = 인덱스명리스트
인덱스명리스트의 항목 수는 인덱스 수와 동일해야한다.
# range(100,3100,100)
df.index = range(100,3100,100)
특정 인덱스명 변경하 df.rename(index={'현재컬럼명1':'바꿀컬럼명1','현재컬럼명2':'바꿀컬럼명2',...}) # 100-->'a', 200-->'b'
df.rename(index={100:'a',200:'b'}, inplace=True)

 

 

4. 데이터에 함수 적용하기

4.1 함수로 컬럼의 데이터 변경하기

  • 컬럼.apply(함수명)
  • 컬럼.apply(함수명, 매개변수명=매개변수값)
    매개변수명을 명시해주어야 한다.
  • 적용할 함수가 미리 정의되어 있어야 한다.

예시1

# 1. df['math']의 모든점수에 5점 더하기.(--> 105점?)
df_copy['math'] = df.math+5
df_copy


# 2. df['math']의 모든점수에 5점 더하기. 100점이 넘을 수 없다.
def plus5(x):
    score = x+5
    if score>=100:
        score=100
    return score

df_copy['math'] = df['math'].apply(plus5)
df_copy
# plus5의 매개변수 x는 df['math'] 데이터를 받는 매개변수!
# 때문에 apply 할 때는 함수명만 전달해주면 된다~

좌측 : 적용 전, 우측 : 순서대로 #1,#2 적용 후

 

예시2

# 모든 점수에 n점 더하기. 100점이 넘을 수 없다.
def plusn(x,n):
    score = x+n
    if score>=100:
        score=100
    return score

# df['eng']의 모든 점수에 1점 더하기. 100점이 넘을 수 없다.
df_copy['eng'] = df['eng'].apply(plusn, n=1)

1씩 증가한 모습

 

4.2 행/열 데이터 집계하기

  • 데이터프레임.apply(함수명, axis=0) : 열단위로 함수가 적용된다.
  • 데이터프레임.apply(함수명, axis=1) : 행단위로 함수가 적용된다.
# 합계 구하기
def get_sum(x):
    return x.sum()
# 행, 열 단위 데이터가 들어오면 합계 구해서 return

 

 

행 단위 적용 - 학생 별 점수 합계

df_copy['sum'] = df.apply(get_sum, axis=1)

 

 

 

 

 

 

 

 

열 단위 적용 -  과목 별 점수 합계

df_copy.loc['sum'] = df.apply(get_sum, axis=0)

 

 

 

 

 

 

 

 

 

5. 결측치 다루기

5.1 결측치란?

NaN, 값이 없는 것! : 통계값을 구할 때 데이터의 개수에 영향을 끼치므로 적절한 처리 필요

 

5.2 결측치 확인 방법

df.isnull().sum() : 널값 개수

df.info() : 전체 정보

 

5.3 결측치 처리 방법

dropna() : 삭제

fillna() : 대치

방법 문법 예시
결측치 삭제 df.dropna() 
: 결측치가 존재하는 모든 행 삭제

df.dropna(axis=1) 
: 결측치가 존재하는 모든 열 삭제
 
결측치 대치
특정 값으로 df.fillna(특정값) df.fillna(0) -> 전부 0 으로
이전 값으로 df.fillna(method='ffill') 이전 값 없으면 대치 X, 그대로 NaN
다음 값으로 df.fillna(method='bfill') 다음 값 없으면 대치 X, 그대로 NaN
컬럼별로 대치할 값 지정 df.fillna({'컬럼명1':값1, '컬럼명2':값2,...}) df.fillna({'A':0,'B':1,'C':2,'D':3})

 

📌 결측치가 포함된 데이터의 통계값?

- 결측치는 없는 데이터로 간주된다.

df['A'].mean() # 3.0
df['B'].mean() # 3.0

 

 

 

 

6. 판다스 자료형

6.1 자료형 종류

int64 : 정수형

float64 : 실수형

bool : 부울형

object : 문자열

category : 카테고리

datetime64 : 날짜, 시간

# 샘플데이터
df = pd.DataFrame({'float': [1.0, 2.0],
                    'int': [1,2],
                    'datetime': [pd.Timestamp('20200101'),pd.Timestamp('20210101')],
                    'string': ['a','b'],
                    'bool':[True,False],
                    'object':[1,'-'], # 정수 + 문자 혼합
                    'float2' : [1.0, 2]}) # 정수 + float = float

자료형, 우측 빨간 박스는 pandas에서만 사용하는 자료형

 

6.2 자료형 처리

방법 문법 예시
자료형 확인 데이터프레임 : df.dtypes
시리즈 : series.dtype

시리즈 데이터 타입 혼합 -> object

시리즈 정수와 실수 혼합 -> float64
시리즈의 경우 : df['int'].dtype
혼합의 경우 : type(df.loc[행,열])
자료형 변환 df.astype('자료형')
series.astype('자료형')
전체 자료형 변환
: df = df.astype('자료형')

object에서 int로
: df = df.astype('float').astype('int') 
object인 데이터를 바로 int로 바꾸는 건 불가능! float으로 바꾸고 int로 넘긴다

특정 컬럼의 자료형 변환
: df['col'] = df['col'].astype('자료')
# 숫자형으로 변환 pd.to_numeric(col, errors='ignore')
: 숫자로 변경할 수 없는 값이 있으면 작업하지 않음

pd.to_numeric(col, errors='coerce')
: 숫자로 변경할 수 없는 값이 NaN으로 설정

pd.to_numeric(col, errors='raise')
: 숫자로 변경할 수 없는 값이 있으면 에러발생(default)
- pd.to_numeric(s2, errors='ignore')
0 1.0
1 2
2 a
dtype : object

- pd.to_numeric(s2, errors='coerce')
0 1.0
1 2.0
3 NaN
dtype : float64
# 시계열 데이터로 변환 pd.to_datetime(col) - astype
df['출생'] = df['출생'].astype('datetime64')

- to_datetime
df['사망'] = pd.to_datetime(df['사망'])

 

👻 자료형이 혼합된 컬럼의 자료형 변환

# col3 컬럼을 str형으로 변환
df['col3'] = df['col3'].astype('str')
type(df.loc[0,'col3']) 
#str


# 변경할 수 없는 자료가 섞여있으면 error
df['col3'] = df['col3'].astype('int')
#error

 

6.3 카테고리형 자료 다루기

(1) 카테고리형?

 

특정 값들로만 이루어지는 자료형! 범주형 데이터를 다룬다. 

ex) 성별, 혈액형, 학점, 지역

 

# 범주형 자료란? 관측 결과가 몇 개의 범주 또는 향목의 형태로 나타나는 자료를 말한다. 

 

 (2) 카테고리형 다루기

목적 사용법 예시
카테고리형으로 변환 컬럼.astype('category') # 자료형 변환하기
df['grade'] = df['grade'].astype('category')
카테고리 요소 이름 바꾸기 컬럼.cat.categories = 카테고리리스트 # 1234 등급을 ABCD로
df['grade'].cat.categories = ['A','B','C','D']
카테고리 추가 컬럼.cat.set_categories(카테고리리스트) # F 끼워넣기
df['grade'] = df['grade'].cat.set_categories(['A','B','C','D','F'])

데이터 용량을 절약할 수 있다는 장점!

 

6.4 시계열 자료 다루기

(1) 시계열 데이터?

 

Pandas에서 날짜와 시간을 다루는 자료형

 

목적 사용법 예시
컬럼을 datetime 자료형으로 변경 pd.to_datetime(컬럼) # 출생, 사망 컬럼을 datetime 자료형으로 변경하기
df['출생'] = pd.to_datetime(df['출생'])
연, 월, 일 분기 추출 컬럼.dt.year
컬럼.dt.month
컬럼.dt.day
컬럼.dt.quarter
year : 1962, 1953 ...
month : 1, 2, 3 ...
day : 20, 21 ...
quarter : 1,2,3,4
날짜 계산 긴 날짜 - 짧은 날 # 연산 시 최소 단위로 결과값 반환
df['생존일수'] = df['사망']-df['출생']
: 24213 days

# 생존기간 컬럼 만들기
df['생존기간'] = df['사망'].dt.year-df['출생'].dt.year
: 56
요일, 월이름 추출 컬럼.dt.strftime('%a') : 요약된 요일이름
컬럼.dt.strftime('%A') : 긴 요일이름
컬럼.dt.strftime('%w') : 숫자요일(0:일요일)
컬럼.dt.strgtime('%b') : 요약된 월이름
컬럼.dt.strftime('%B') : 긴 월이름
%a : Thu, Fri ...
%b : Jan, Feb ...
datetime 자료형을 인덱스로 만들어 사용 df.index = df['컬럼'] # 출생 컬럼을 인덱스로 만들기
df.index = df['출생']
# 1955년 출생한 사람 데이터 추출하기
df.loc['1955']

# 1955년 2월 출생한 사람 데이터 추출하기
df.loc['1955-02']

 

 

7. 데이터 프레임 합치기 (concat, merge)

7.1 데이터프레임 연결하기 concat

  • pd.concat(데이터프레임리스트)
    데이터프레임이 동일한 컬럼명 기준으로 행으로 연결된다.
  • pd.concat(데이터프레임리스트, axis=1)
    데이터프레임이 동일한 인덱스 기준으로 열로 연결된다.

 

  예시
  행으로 연결하기
  df1 df2 df3
합칠 테이블



  1. 컬럼명 기준으로 연결 2. 공통된 컬럼만 남기기
(join='inner')
3. 인덱스 재지정
(ignore_index=True)
concat 예시 pd.concat([df1,df2,df3])

pd.concat([df1,df2,df3],
 join='inner')

pd.concat([df1,df2,df3], join='inner',
ignore_index=True)




  열로 연결하기
  df4 df5 df6
합칠 테이블



  1. 인덱스 기준으로 연결 2. 공통된 인덱스 남기기  
  pd.concat([df4,df5,df6], axis=1)


pd.concat([df4,df5,df6], axis=1,
join='inner'
)


 

 

 

7.2 공통된 열 기준으로 연결하기 merge

  • pd.merge(left,right,on=기준컬럼,how=연결방법)
  • 2개의 데이터프레임을 연결한다.

 

  예시
  df7 df8
합칠 테이블
  1. 공통 데이터만으로 연결
how='inner' (default)
2. 모든 행 연결
how='outer'
merge 예시 pd.merge(df7, df8, on='name', how='inner')



pd.merge(df7, df8, on='name', how='outer')

  3. 왼쪽 데이터프레임 기준으로 연결
how='left'
4. 오른쪽 데이터프레임 기준으로 연결
how='right'
  pd.merge(df7, df8, on='name', how='left')

pd.merge(df7, df8, on='name', how='right')

 

 

8. 행/열 형태 변경 (melt, pivot)

8.1 행을 열로(값으로) 보내기! melt

  • 데이터프레임.melt()
  • pd.melt(데이터프레임)
melt 예시
예제 테이블
 
  1. 모든 열 melt
df.melt( ), pd.melt(df)
2. 고정할 컬럼 지정하여 melt
id_vars=[열이름리스트]
 --> 위치를 그대로 유지할 열 이름
 
# name, kor 고정
df.melt(id_vars=['name','kor']

 
melt 예시 3. 행으로 위치를 변경할 열 지정
value_vars=[열이름리스트]
4. 컬럼명 변경
var_name=컬럼명 --> value_vars로 위치를 변경한 열 이름
value_name=var_name으로 위치를 변경한 열의 데이터를 저장한 열 이름
  # kor, eng
df.melt(id_vars='name',
value_vars=['kor','eng'])

# subject, score
df.melt(id_vars='name', value_vars=['kor','eng'], 
var_name='subject', 
value_name='score')

 

 

8.2 열을 행으로 보내기! pivot

  • df.pivot( index=인덱스로 사용할 컬럼, columns=컬럼으로 사용할 컬럼, values=값으로 사용할 컬럼 )

 

샘플데이터 생성

# 샘플데이터
df = pd.read_csv('data/scores.csv')
df = df.head(2)
df = df.melt(id_vars = 'name', var_name='subject',value_name='score')

def get_grade(x):
    if x>=90: grade='A'
    elif x>=80: grade='B'
    elif x>=70: grade='C'
    elif x>=60: grade='D'
    else: grade='F'
    return grade

df['grade'] = df['score'].apply(get_grade)
df = df.sort_values('name')
df

 

예시 1. 인덱스=name, 컬럼=subject, values=score

df.pivot(index='name', columns='subject',values='score')

적용 전 / 적용 후

 

예시 2. 인덱스=name, 컬럼=subject, valyes=[score, grade]

df.pivot(index='name', columns='subject',values=['score','grade'])

적용 전 / 적용 후

 

8.3 행과 열 바꾸기

df.transpose()

적용 전 / 적용 후

 

9. 데이터 집계하기(pivot, groupby)

9.1 pivot_table 데이터 집계

  • 피벗테이블은 표의 데이터를 요약하는 통계표이다.
  • pd.pivot_table(데이터프레임, index=인덱스, columns=컬럼, values=집계할데이터, aggfunc=통계함수)
  • aggrunc의 디폴트는 mean

사용 데이터

# 샘플데이터
df = pd.DataFrame({"item": ["shirts", "shirts", "shirts", "shirts", "shirts",
                          "pants", "pants", "pants", "pants"],
                    "color": ["white", "white", "white", "black", "black",
                          "white", "white", "black", "black"],
                   "size": ["small", "large", "large", "small",
                          "small", "large", "small", "small",
                         "large"],
                   "sale": [1, 2, 2, 3, 3, 4, 5, 6, 7],
                   "inventory": [2, 4, 5, 5, 6, 6, 8, 9, 9]})

 

# item, size별 재고 합계

df.pivot_table(index='item', columns='size',values='inventory' ,aggfunc='sum')

 

 

 

 

 

# [item,color], size별 재고 합계

df.pivot_table(index=['item','color'],columns='size', values='inventory', aggfunc='sum')

 NULL 0처리는? fill_value=0 추

 

 

 

 

# [item,color], size별 판매,재고 합계

df.pivot_table(index=['item','color'], columns=['size'], values=['sale','inventory'], aggfunc='sum')

 

 

 

 

9.2 groupby 데이터 집계

  • df.groupby(그룹기준컬럼).통계적용컬럼.통계함수
  • count() : 누락값을 제외한 데이터 수
  • size() : 누락값을 포함한 데이터 수
  • mean() : 평균
  • sum() : 합계
  • std() : 표준편차
  • min() : 최소값
  • max() : 최대값
  • sum() : 전체 합

(1) 그룹에 사용자 정의함수 적용하기

  • df.groupby(그룹기준컬럼).통계적용컬럼.agg(사용자정의함수,매개변수들)
def my_mean(values):
    return sum(values)/len(values)

df.groupby(['Sex','Pclass']).Survived.agg(my_mean)

 

(2) 그룹 오브젝트 출력하기

  • 데이터프레임.groupby(그룹기준컬럼).groups --> 그룹별 인덱스:[데이터리스트] 출력
  • 데이터프레임.groupby(그룹기준컬럼).get_group(그룹인덱스) --> 그룹별 인덱스에 해당하는 데이터프레임 출력

 

# Pclass 그룹별 인덱스
df20.groupby('Pclass').groups

#{1: [1, 3, 6, 11], 2: [9, 15, 20, 21], 3: [0, 2, 4, 7, 8, 10, 12, 13, 14, 16, 18, 22]}

 

 

 

 

 

 

🚨 Pclass 그룹 출력(1등석)

df20.groupby('Pclass').get_group(1)

 

 

🚨 Pclass 그룹 출력(2등석)

df20.groupby('Pclass').get_group(2)

 

 

 

#유데미, #유데미코리아, #유데미부트캠프, #취업부트캠프, #부트캠프후기, #스타터스부트캠프, #데이터시각화 #데이터분석 #태블로

Comments