자신에게 친절할 것 :)

Data Science/Pandas

[데이터 전처리] 데이터 구간화 cut() or apply(), 람다함수와 apply()

Tashapark 2024. 6. 21. 15:38
728x90
반응형

# 코드잇 데이터 사이언티스트 강의 듣는 중


 

<데이터 구간화 Binning>

 

- 연속적 숫자 데이터를 여러 구간으로 분류

 

 

 

 

 

 

- 우선 구획화하고 싶은 값의 최소/최대값을 확인

patient_df['age'].describe()

 

--> 최소 20, 최대 69

--> 즉 20대부터 총 60대까지로 구성

 

 

 

 

 

- pd.cut()

- pd의 메소드임. 파라미터로 여러가지 조건들을 계속 넣어줄 수 있음. 

- bins = --> 구간 설정 시 사용

pd.cut(patient_df['age'], bins=[20, 30, 40, 50, 60, 70])

 

--> 옆에처럼 나눠주고 싶은 구간을 지정(연령대)해도 되고,

그냥 숫자를 넣으면 (예, 3) 그 수만큼 알아서 나눠주기도 함.

 

 

 

 

 

 

patient_df['age_group'] = pd.cut(patient_df['age'], 
                                 bins=[20, 30, 40, 50, 60, 70])

 

 

 

 

 

 

 

 

--> 함수 안의 파라미터는 \ 안써도 엔터 가능

--> ( 숫자 포함 x. 즉, 초과 미만 

--> ]는 숫자 포함.  즉, 이상 이하 

--> ( ]가 디폴트임

--> so, 20이 결측치됨. 

 

 

- 범위 변경

patient_df['age_group'] = pd.cut(patient_df['age'], 
                                 bins=[20, 30, 40, 50, 60, 70],
                                 right=False) # 왼쪽 포함, 오른쪽 아님

 

 

 

 

 

 

--> right = False라고만 했는데도  [ )로 양 쪽이 바뀜.

--> 20대 포함 시킴.

 

 

 

 

- 값 변경 

patient_df['age_group'] = pd.cut(patient_df['age'], 
                                 bins=[20, 30, 40, 50, 60, 70],
                                 right=False,
                                 labels=['20s', '30s', '40s', '50s', '60s'])

 

 

 

 

 

 

--> labels = []에 값을 넣어주면 변경가능.

--> 그냥 처음 순서대로만 넣어 주면 됨. 

 

--> labels는 bins 보다 값이 하나 작아야 함. 

-->  describe해서 최소, 최대값도 넣을 것.


<예제>

bmi_max = patient_df['bmi'].max()
patient_df['obesity'] = pd.cut(patient_df['bmi'],
                               bins=[0, 18.5, 25, 30, bmi_max],
                               labels=['under', 'healthy', 'over', 'obese'],
                               right=False)
patient_df

 

--> 이런 식으로 그냥 최소에 0을 주고, 최대값으로 max를 해줘도 간단해짐. 

 

 


- apply() 

- 다른 함수를 argument 인자로 사용. 

- dataframe이나 series의 값 하나하나에 인자로 받은 함수를 적용

import pandas as pd

df = pd.DataFrame([[1, 9], [4, 16]], columns=['column1', 'column2'])
df

 

-->  만약, column2의 제곱근을 구하고자 하면, 

np.sqrt()를 이용 

 

import numpy as np

np.sqrt(4)  #2

 

- apply()로 데이터 프레임에 적용하고 싶으면, ()를 쓰면 안됨. 

df['column2'].apply(np.sqrt)

 

 

 

 

 

- 우선 구획화하고 싶은 값의 최소/최대값을 확인

patient_df['age'].describe()

 

--> 최소 20, 최대 69

--> 즉 20대부터 총 60대까지로 구성

 

 

 

 

 

- python  함수 사용

- if문으로 각각의 return 값에 밸류를 넣어줌. 

def group_age(x):
    if x >= 10 and x < 20:
        return '10s'
    elif x >= 20 and x < 30:
        return '20s'
    elif x >= 30 and x < 40:
        return '30s'
    elif x >= 40 and x < 50:
        return '40s'
    elif x >= 50 and x < 60:
        return '50s'
    else:
        return '60s'

 

- .apply(함수명) 

patient_df['age_group'] = patient_df['age'].apply(group_age)

 

--> 이러면 바로 들어감.

 

 

 

 

 

=> apply()의 특장점은 다양한 상황에서 쓸 수 있는 것으로 필요한 함수를 만들어서 넣어주기만 하면 됨. 

- cut()이 데이터 구간화를 위해 만들어진 것이기에 코드가 더 간결하지만, 

- 원하는 함수를 찾아서 쓰거나 직접 만들어서 쓸 때는 apply()를 사용하면 됨. 

 


<람다 함수와 apply()>

 

- 람다 함수: def 로 함수를 정의할 필요 없이, 다른 함수에서 바로 사용 가능. 이름이 없다는 뜻으로 '익명 함수 anonymous function' 이라고도 함. 

- 나중에 다시 사용할 필요 없으면, 걍 람다함수로 만들면 메모리도 절약되고, 코드도 더 간결해짐. 

def multiply_two(x):
    return 2*x

 

- 이걸 람다함수로 바꾸면 훨씬 간단해짐. 

- lambda 파라미터 문자: return 값

lambda x: 2*x

 

- 만약 키의 기준값인 미터를 인치로 바꾸고 싶다면, 

patient_df['height'].apply(lambda x: 39.370079*x)

--> 1m의 인치 값인 약 39.370079를 곱해 줌.

--> then, apply()로 series 값에 하나씩 접근해서 람다 함수 적용.

--> ? 마치 for문 같은데? 

 

-but, 위의 식은 너무 간단해서 아래 처럼 하면 더 짧고 빠름 

patient_df['height'] * 39.370079

 

 

- if 문을 사용하면 더 유용하게 사용 가능. 

-  lambda 파라미터 문자: 참일 때 return 값  if문  else  거짓일 때 return 값

--> bmi 값이 30을 넘으면 Y, 아니면 N 리턴하게 만들고 싶음. 

patient_df['bmi'] = round(patient_df['weight'] / patient_df['height']**2, 1)
patient_df['bmi'].apply(lambda x: 'Y' if x > 30 else 'N')

 

 

- 구간으로 if문 주기

- 어떤 값 사이는 Y, 아니면 N

--> 함수를 만들어서 사용함

def isin_interval(x, n_lower, n_upper):
    if n_lower <= x < n_upper:
        return 'Y'
    else:
        return 'N'

 

- 람다함수에 함수를 적용할 때는 해당 함수의 파라미터도 전부 넣어줘야 함. 

patient_df['bmi'].apply(lambda x: isin_interval(x, 18.5, 25))

- x는 dataframe의 BMI 값이고, n_lower, n_upper는 원하는 값을 넣어주면 됨. 

- 보통 bmi는  18.5 ~25는 정상 체중임. 

- 다른 구간을 구하려고 하면 숫자만 바꿔서 넣어주면 됨.

patient_df['bmi'].apply(lambda x: isin_interval(x, 25, 30))
728x90
반응형