2024.01.05 TIL

녹차·2024년 1월 24일

TIL_Python

목록 보기
6/9

01-DataFrame심화-데이터셋 확인하기

customers= pd.read_csv('marketing_campaign.csv', sep='\t')
customers.head()
  • marketing_campaign.csv 을 customers라는 이름의 데이터프레임으로 생성
customers.info()
  • 각 컬럼별 결측값과 타입 확인하기
# 집계통계 기술
customers.describe().round(1)
  • 숫자형 데이터 값 집계하기
# 집계통계 기술 - 숫자 아닌 정보 확인
# 집계통계 기술
customers.describe(exclude=['int','float']).round(1)
  • 숫자 아닌 정보 확인

02 DataFrame과 Series 각 데이터 함수적용(apply)

# 나이 계산 - 데이터셋이 2021.08.23임
2021 - customers['Year_Birth']
  • 나이계산하기 위해 현재년에서 customers['Year_Birth'] 빼기
ID
5524     64
2174     67
4141     56
6182     37
5324     40
         ..
10870    54
4001     75
7270     40
8235     65
9405     67
Name: Year_Birth, Length: 2240, dtype: int64
# 연도 옆에 추가
customers.insert(1, 'Age', 2021 - customers['Year_Birth'])
customers.head()
  • 완성된 나이 데이터를 연도 옆에 추가

  • **.apply(func)**
    • 시리즈에 각 함수 실행결과를 적용시킨다
def classify_age(age):
    if age >= 0 and age <= 12:
        return 'Child'
    elif age >= 13 and age <= 19:
        return 'Teenager'
    elif age >= 20 and age <= 39:
        return 'Young_Adult'
    elif age >= 40 and age <= 64:
        return 'Middle_aged'
    elif age >= 65:
        return 'Elderly'
    else:
        return 'Inavlid_age'
  • 나이를 구분하는 함수 생성
classify_age(9), classify_age(17), classify_age(20), classify_age(59), classify_age(65)

('Child', 'Teenager', 'Young_Adult', 'Middle_aged', 'Elderly')

customers['Age'].apply(classify_age)
ID
5524     Middle_aged
2174         Elderly
4141     Middle_aged
6182     Young_Adult
5324     Middle_aged
            ...
10870    Middle_aged
4001         Elderly
7270     Middle_aged
8235         Elderly
9405         Elderly
Name: Age, Length: 2240, dtype: object

03 Series값매핑과 DataFrame 요소함수적용

  • **Series.map(arg)**
people_set = {
    'Name' : ['Spencer', 'Mark', 'Tom', 'Peter'],
    'Major': ['Computer', 'Science', 'English', 'Computer'],
    'YearOfJoining' : [2020, 2019, 2018, 2017],
    'DriverLicense' : [True, False, False, True],
    'TeacherCertification' : [True, False, False, False],
}
NameMajorYearOfJoiningDriverLicense
0SpencerComputer2020True
1MarkScience2019False
2TomEnglish2018False
3PeterComputer2017True
# map() 으로 매핑 확인해서 값 변환
people['DriverLicense'].map({True :'Yes', False: 'No'})
  • map() 으로 매핑 확인해서 값 변환
0    Yes
1     No
2     No
3    Yes
Name: DriverLicense, dtype: object

  • **Dataframe.applymap(func)**
    • 모든 요소에 apply()를 할 수 있다.
people.applymap(type)

people.applymap(str).applymap(type)
# str같은 경우 Series는 applymap할 필요 없이 가능하나
people['Name'].str.len()

# Dataframe은 .str이 안된다.
people.str()
  • 모든 요소를 str로 변환하고 대문자로 변환하면
# 대문자 만드는 함수
def uppercase(data):
    return data.upper()

people.applymap(str).applymap(uppercase)

04 DataFrame심화-타입 변환(astype)

  • .astype(dtype)로 형변환
    • NA는 형변환이 불가
    • 이번 실습으로 데이터프레임의 메모리를 줄여보자. 이를 위해 int64를 int8로 줄일 예정
      • int64는 64비트를 표현 가능한 범위를 사용
      • int8은 8비트로 표현 가능한 범위를 사용
dtype설명
int64정수형 데이터
float64실수형 데이터
object문자열 데이터
bool불리언(참/거짓) 데이터
datetime64날짜 및 시간 데이터
timedelta두 날짜 또는 시간 간격 데이터
category카테고리 형식의 데이터
int88비트 정수형 데이터
int1616비트 정수형 데이터
int3232비트 정수형 데이터
float1616비트 실수형 데이터
float3232비트 실수형 데이터
complex6464비트 복소수형 데이터
complex128128비트 복소수형 데이터
# int64 -> int16 탄생연도
customers['Year_Birth'].astype('uint16')

05 DataFrame심화-값 교체(replace)

customers["Marital_Status"].value_counts()
결혼 상태인원 수
Married864기혼
Together580동거
Single480독신
Divorced232이혼
Widow77미망
Alone3혼자, 싱글
Absurd2터무니없는
YOLO2욜로 인생

이 중 Alone, Absurd, YOLO는 해석에 애매한 부분이 있다.
해당 데이터의 토론에도 이슈가 있으며
YOLO같은 경우는 일반적인 Single과는 다른 고객패턴이 있음을 표시하고 싶었던 것 일수도.

여기서는 이 3가지를 Single로 귀속시켜보자.

# 방법 1. 시리즈.replace(dict)
customers["Marital_Status"].replace({'Alone' : 'Single', 'Absurd' : 'Single' , 'YOLO' :'Single'})
# 방법 2. 시리즈.replace(to_replace:list, value)
customers["Marital_Status"].replace(['Alone', 'Absurd', 'YOLO'], 'Single')
# 방법 3. 데이터프레임.replace()
customers.replace({'Alone' : 'Single', 'Absurd' : 'Single' , 'YOLO' :'Single'})
# Inplcae=True로 원본에 반영하기
customers.replace({'Alone' : 'Single', 'Absurd' : 'Single' , 'YOLO' :'Single'}, inplace=True)

06 DataFrame심화-조건식(where)

  • where을 사용하여 **다자녀(2인 이상)을 확인**
customers.where(customers['Kidhome'] >= 2)
  • 조건에 맞는 데이터가 아니면 NA를 반환한다.
# .where()이후 .dropna()
customers.where(customers['Kidhome'] >= 2).dropna()
  • 다자녀가 아니면 데이터프레임에서 제거후 출력

  • 조건에 맞지 않느 데이터 은닉 방법

# 방법 1. other로 대체하기
customers.where(customers['Kidhome'] >= 2, other='ooo')
# 방법 2. default인 NA가 되도록 놓거나 other에 None으로 대체하기
customers.where(customers['Kidhome'] >= 2, other='None')

07 DataFrame심화-여러 집계함수동시적용(agg)

  • .agg()

  • 지정된 축(axis)을 기준으로 하나 이상의 연산을 사용하여 데이터를 집계(aggregate) 하는 기능을 제공

  • parameter

    • func : function, str, list or dict
      • 데이터를 집계하는 데 사용할 함수를 지정.
      • 함수로는 DataFrame을 인자로 받을 수 있는 함수나 DataFrame의 apply() 메소드에 사용할 수 있는 함수여야 한다.
      • 허용 가능한 조합
        • 함수
        • 함수 이름의 문자열
        • 함수나 함수 이름이 포함된 리스트
        • 축 레이블과 함수 또는 함수 이름이 포함된 딕셔너리 형태의 조합
    • axis : {0 or ‘index}
      • 데이터를 집계할 축을 지정.
      • 0 또는 'index'인 경우 각 열(column)을 기준으로 함수를 적용.
      • 1 또는 'columns'인 경우 각 행(row)을 기준으로 함수를 적용.
    • args와 *kwargs: 함수에 전달할 위치 인자와 키워드 인자를 지정할 수 있다.
  • return

  • scalar, Series or DataFrame

    • Scalar: Series.agg() 메소드가 단일 함수로 호출될 때 반환됩니다.
    • Series: DataFrame.agg() 메소드가 단일 함수로 호출될 때 반환됩니다.
    • DataFrame: DataFrame.agg() 메소드가 여러 함수로 호출될 때 반환됩니다.
# 방법1. dict로 전달
# Income -> max, Kidhome -> mean
customers.agg({'Income' : 'max', 'Kidhome' : 'mean'})
Income     666666.000000
Kidhome         0.444196
dtype: float64
# 방법2. dict없이 str 또는 list로 전달하기
customers.agg('max')

# max, min
customers.agg(['max', 'min'])

# max, min, mean
customers.agg(['max', 'min', 'mean'])
  • customers 데이터프레임의 ['Education', 'Marital_Status', 'Dt_Customer'] 열에 숫자형이 아닌 데이터가 포함되어 있기 때문에 에러가 발생.
  • 이를 방지하기 위해 이러한 열을 집계 연산에서 제외하거나, 원본에서 해당 열을 삭제.
# 대처 1 : drop() agg() 체인형으로 해결
customers.drop(columns=['Education', 'Marital_Status', 'Dt_Customer']).agg(['max', 'min', 'mean'])
# 대처 2 : 새로운 df를 만들어 해결
customers_nemeric = customers.select_dtypes(include='number')
customers_nemeric.agg(['max', 'min', 'mean'])
# 대처 3 : 원본에서 제거. 대처1을 파괴적으로 처리하는 방법
customers.drop(columns=['Education', 'Marital_Status', 'Dt_Customer'], inplace=True)
customers_nemeric.agg(['max', 'min', 'mean'])

⛔ agg()는 numeric_only=True가 안된다.
  • 간혹 숫자형 데이터만 집계하기위해 agg()에 numeric_only=True쓰는 경우가 있는데 무의미한 코드이다. 생각보다 쉽게 보이는 코드 실수.
customers.agg(['max', 'min', 'mean'], numeric_only=True)

# numeric_only=True는 agg() 메소드에는 적용되지 않는 옵션
# numeric_only=True 옵션은 max(), min(), mean() 등과 같은 집계 함수에 적용될 때 사용

08 DataFrame심화-데이터프레임 복제(copy, equals)

  • copy() - 데이터프레임/시리즈의 복제
    • 원본과 분리해서 작업하고 싶을 때 사용
# 복제 방법
customers_copy = customers.copy()
# 주소 비교
id(customers), id(customers_copy)

(2273371876880, 2273376423824)

  • 주소가 다르다

09 DataFrame심화-멀티인덱싱

  • 멀티인덱스? 멀티인덱싱?

    • https://pandas.pydata.org/docs/reference/api/pandas.MultiIndex.html#pandas.MultiIndex
    • 하나 이상의 인덱스 레벨을 가지는 인덱스 구조.
    • 데이터프레임이나 시리즈의 다차원적인 인덱싱을 지원하기 위해 사용.
    • 멀티인덱스로 인해 데이터를 계층적(hierarchical)으로 조직화.
    • 다양한 차원(Multi-level)에서 데이터에 접근 가능.
    • 멀티인덱스 생성은 데이터프레임 또는 시리즈를 생성할 때 인덱스를 array같은 형태로 지정한다.
  • 멀티 인덱스 설정 방법 1

customers = pd.read_csv('marketing_campaign.csv', sep='\t', index_col=['ID', 'Marital_Status'])
customers
  • 인덱스가 2개 생성
IDMarital_Status

  • set_index()로 인한 멀티인덱스 설정
customers.set_index(['ID', 'Marital_Status'], inplace=True)
MultiIndex([( 5524,   'Single'),
            ( 2174,   'Single'),
            ( 4141, 'Together'),
            ( 6182, 'Together'),
            ( 5324,  'Married'),
            ( 7446, 'Together'),
            (  965, 'Divorced'),
            ( 6177,  'Married'),
            ( 4855, 'Together'),
            ( 5899, 'Together'),
            ...
            ( 7004,   'Single'),
            ( 9817,   'Single'),
            ( 8080,   'Single'),
            ( 9432, 'Together'),
            ( 8372,  'Married'),
            (10870,  'Married'),
            ( 4001, 'Together'),
            ( 7270, 'Divorced'),
            ( 8235, 'Together'),
            ( 9405,  'Married')],
           names=['ID', 'Marital_Status'], length=2240)

  • .get_level_values(level)
customers.index.get_level_values(0)
  • 인덱스 레벨이 0인 것만 출력

  • .swaplevel()

customers.swaplevel()
profile
가장 예쁜 꽃은 우여곡절 끝에 피는 꽃

0개의 댓글