[AI][Data Analysis and Machine Learning]Pandas-DataFrame_2

·2025년 3월 6일
post-thumbnail

one-hot encoding

범주형 데이터 전처리

  • 범주형 데이터는 분석단계에서 계산이 어렵기 때문에 숫자형으로 변경이 필요
  • 범주형 데이터의 각 범주를 column레벨로 변경
  • 해당 범주에 해당하면 1, 아니면 0으로 채우는 인코딩 기법
  • pandas.get_dummies 함수 사용
  • columns= 파라미터로 one-hot encoding 컬럼으로 만들어질 컬럼들을 지정해줄 수 있다.
pd.get_dummies(df,columns=['Pclass','Sex','Embarked']
  • 0/1 로 하려면
pd.get_dummies(df,columns=['Pclass','Sex','Embarked'],dtype=int)
  • drop_first: 첫번째 카테고리 값은 사용하지 않음
pd.get_dummies(df,columns=['Pclass','Sex','Embarked'],dtype=int,drop_first=True)

groupby

  • 데이터를 특정 컬럼으로 묶어서 긃화
  • 아래의 세 단계를 적용하여 데이터를 그룹화
    • 데이터 분할(split)
    • operation 적용(apply)
    • 데이터 병합(combine)

groupby(), groups 속성

  • 각 그룹과 그룹에 속한 index를 dict 형태로 표현
  • groupby(컬럼 혹은 컬럼의 리스트)
    grouped_pclass=df.groupby('Pclass')
    
    grouped_pclss 는 DataFrameGroupBy 객체임
  • groupby 객체의 속성
    • groups : dict 형태
    • key: 컬럼의 각 값
    • value: 인덱스 값들의 list
      grouped_pclass.groups
      #Pclass의 값은 1,2,3 뿐. 즉 그룹의 수는 3개다
      #groups의 key값은 Pclass의 값들
      #value는 index들의 list 
  • size(): 각 그룹별로 담겨 있는 데이터 개수 확인
    grouped_pclass.size()
    0
    Pclass
    1
    2
    3
    dtype: int64

get_group

  • 그룹별 DataFrame 리턴

#pclass 가 1인 그룹의 DataFrame 리턴 
grouped_pclass.get_group(1)
#female 인 그룹의 DataFrame 리턴
grouped_sex.get_group('fdmale')

groupby 객체의 기초 연산 메소드

  • 그룹 데이터에 적용가능한 통계 함수(NaN은 제외하여 연산)
  • count: 데이터 개수
  • sum: 데이터 합
  • mean,std,var: 평균, 표준편차,분산
  • min,max: 최소, 최대값

index를 이용한 groupby()

  • index 가 있는 경우, groupby 함수에 level 사용 가능
    • level 은 index의 depth 를 의미, 가장 왼쪽 부터 0부터 증가
  • set_index 함수
    • column 데이터를 index 레벨로 변경

      df.set_index('Pclass')
      
PassengerIdNameSex
Pclass
31Braund, Mr. Owen Harrismale
  • reset_index 함수
    • 인덱스 초기화

      df.set_index(['Pclass','Sex']).reset_index()
PclassSexPassengerIdSurvivedName
03male10Braund, Mr. Owen Harris
11female21Cumings, Mrs. John Bradley (Florence Briggs Th...
23female31Heikkinen, Miss. Laina

groupby(함수)

  • 함수의 매개변수는 index
  • 함수가 리턴하는 값이 grouping 기준이 된다

나이대별 생존률 구하기

df.set_index('Age')
AgePassengerIdSurvivedPclassName
22.0103Braund, Mr. Owen Harrismale

..

  • groupby() 에 전달될 함수
    • 전달되는 매개변수는 index

    • 리턴값이 곧 grouping 의 기준

      age_categorize(34)
      >30
  • 나이대별 생존률
df.set_index('Age').groupby(age_categorize)['Survived'].mean() 

이름(name) 시작알파벳으로 승객수 집계

def alpha_categorize(Name):
	return Name[0]
	
	
alpha_categorize('David')
>'D'

df.set_index('Name').groupby(alpha_categorize)['PassengerId'].count()
def get_first_alphabet(name):
	return name[0].upper()
	
df.set_index('Name').groupby(get_first_alphabet)['PassengerId'].count()
df.set_index('Name').groupby(lambda x:x.upper()[0]).size() 

aggregate(집계)함수 사용하기

  • groupby 결과에 집계함수 적용하여 그룹별 데이터 확인가능
df.groupby(['Pclass','Sex'])['PassengerId'].aggregate([np.num,np.mean])
summean
PclassSex
1female44106469.212766
male55599455.729508
2female33676443.105263
male48380447.962963
3female57561399.729167
male158064455.515850

sort_values(), sort_index()

값 기준 정렬, index 기준 정렬

  • by= 정렬기준
  • 컬럼면, 컬럼들의 리스트
  • Pclass 1-2-3 오름차순 정렬
df.sort_values(by='Pclass')
  • Pclass 내림차순 정렬
df.sort_values(by='Pclass', ascending=False)
  • 우선 Pclass 오름차순, 그리고 Age 오름차순
df.sort_values(by=['Pclass','Age'])

pivot, pd.pivot_table 함수

df = pd.DataFrame({
    '지역': ['서울', '서울', '서울', '경기', '경기', '부산', '서울', '서울', '부산', '경기', '경기', '경기'],
    '요일': ['월요일', '화요일', '수요일', '월요일', '화요일', '월요일', '목요일', '금요일', '화요일', '수요일', '목요일', '금요일'],
    '강수량': [100, 80, 1000, 200, 200, 100, 50, 100, 200, 100, 50, 100],
    '강수확률': [80, 70, 90, 10, 20, 30, 50, 90, 20, 80, 50, 10]
                  })

df
지역요일강수량
0서울월요일100
1서울화요일80
2서울수요일1000
3경기월요일200

..

pivot()

  • dataframe의 형태를 변경
  • 인덱스, 컬럼, 데이터로 사용할 컬럼 명시

pivot(index=None,columns=None,values=None)

  • 지역별로 요일별 강수량/강수확률을 보고싶은 경우

df.pivot(index=’지역’,columns=’요일’)

강수량강수확률
요일금요일목요일수요일월요일화요일금요일목요일수요일월요일화요일
지역
경기100.050.0100.0200.0200.010.050.080.010.020.0
부산NaNNaNNaN100.0200.0NaNNaNNaN30.0

pd.pivot_table()

  • 기능적으로 pivot 과 동일
  • pivot과의 차이점
    • 중복되는 모호한 값이 있을 경우 aggregation함수 사용하여 값 채움

stack & unstack

  • stack: 컬럼 레벨에서 인덱스 레벨(row)로 dataframe 변경
    • 데이터를 쌓아올리는 개념
  • unstack: 인덱스 레벨에서 컬럼 레벨로 dataframe 변경
    • stack의 반대
지역요일강수량
0서울월요일100
1서울화요일80
2서울수요일1000
3경기월요일200
4경기화요일200
new_df = df.set_index(['지역','요일'])
new_df
강수량강수확률
지역요일
서울월요일10080
화요일8070
수요일100090
경기월요일20010
화요일20020
부산월요일10030
서울목요일5050
금요일10090
부산화요일20020
경기수요일10080
목요일5050
금요일10010

unstack() : index(row) →column

  • new_df 의 경우 지역의 인덱스 레벨=0, 오른쪽 끝 인덱스 ‘요일’
new_df.unstack() 
강수량강수확률
요일금요일목요일수요일월요일화요일금요일목요일수요일월요일
지역
경기100.050.0100.0200.0200.010.050.080.010.0
부산NaNNaNNaN100.0200.0NaNNaNNaN30.0
서울100.050.01000.0100.080.090.050.090.080.0

stack() : column→index(row)

  • 모든 컬럼을 다 내리면⇒Series
    • df2.stack().stack() 

pd.concat()

DataFrame 병합

  • pandas.concat 함수
  • 축을 따라 dataframe 병합 가능
    • axis=0 : 행단위 병합
    • axis=1 : 열단위 병합
df1 = pd.DataFrame({'key1' : np.arange(10), 'value1' : np.random.randn(10)})
df2 = pd.DataFrame({'key1' : np.arange(10), 'value1' : np.random.randn(10)})

df1

key1value1
000.299311
111.254077
22-0.731377
33-1.906425
441.377054
550.015715
660.591958
771.400798
88-0.220856
992.383409

df2

key1value1
000.301718
11-1.734791
220.785245
332.621160
44-0.722719
550.648751
66-0.089522
77-0.244356
881.581203
99-0.345149
  • 행 방향으로 병합 (axis=0)
pd.concat([df1,df2]) 
key1value1
000.299311
111.254077
22-0.731377
33-1.906425
441.377054
550.015715
660.591958
771.400798
88-0.220856
992.383409
000.301718
11-1.734791
220.785245
332.621160
44-0.722719
550.648751
66-0.089522
77-0.244356
881.581203
99-0.345149
  • 열 방향 병합
pd.concat([df1,df2],axis=1)
key1value1key1value1
000.29931100.301718
111.2540771-1.734791
22-0.73137720.785245
33-1.90642532.621160
441.3770544-0.722719
550.01571550.648751
660.5919586-0.089522
771.4007987-0.244356
88-0.22085681.581203
992.3834099-0.345149
  • column/index 가 다른 경우 ? ?

⇒병합 시 서로에게 없는 컬럼값은 Nan으로 채워짐

pd.merge()

데이터프레임 병합과 조인

dataframe merge

  • SQL 의 join 처럼 특정한 column을 기준으로 병합
    • join 방식: how 파라미터 통해 명시
      • inner: 기본값, 일치하는 값 있는 경우
      • left: left outer join
      • right: right outer join
      • outer: full outer join
  • pandas.merge 함수가 사용됨
customer = pd.DataFrame({'customer_id' : np.arange(6),
                    'name' : ['철수'"", '영희', '길동', '영수', '수민', '동건'],
                    '나이' : [40, 20, 21, 30, 31, 18]})

customer
customer_idname나이
00철수40
11영희20
22길동21
33영수30
44수민31
55동건18
orders = pd.DataFrame({'customer_id' : [1, 1, 2, 2, 2, 3, 3, 1, 4, 9],
                    'item' : ['치약', '칫솔', '이어폰', '헤드셋', '수건', '생수', '수건', '치약', '생수', '케이스'],
                    'quantity' : [1, 2, 1, 1, 3, 2, 2, 3, 2, 1]})
orders
customer_iditemquantity
01치약1
11칫솔2
22이어폰1
32헤드셋1
42수건3
53생수2
63수건2
71치약3
84생수2
99케이스1
  • 고객 X 구매내역
  1. pd.merge(customer,orders,on=’customer_id’)
customer_idname나이itemquantity
01영희20치약1
11영희20칫솔2
21영희20치약3
32길동21이어폰1
42길동21헤드셋1
52길동21수건3
63영수30생수2
73영수30수건2
84수민31생수2
  • customer_id 컬럼을 기준으로 merge 됨
  • 기본적으로 inner join 이기에 조건에 맞지 않으면 빠진다(how=”inner”)
    • customer 테이블의 동건,철수 빠졌고 orders 테이블에서는 9번 customer가 주문한 내용이 빠짐
  1. left outer join

pd.merge(customer,orders,on=’customer_id’,how=’left’)

  • customer 가 left 이다. 즉, 철수,동건이 보인다.
customer_idname나이itemquantity
00철수40NaNNaN
11영희20치약1.0
21영희20칫솔2.0
31영희20치약3.0
42길동21이어폰1.0
52길동21헤드셋1.0
62길동21수건3.0
73영수30생수2.0
83영수30수건2.0
94수민31생수2.0
105동건18NaNNaN
  1. right outer join

pd.merge(customer,orders,on=’customer_id’,how=’right’)

customer_idname나이itemquantity
01영희20.0치약1
11영희20.0칫솔2
22길동21.0이어폰1
32길동21.0헤드셋1
42길동21.0수건3
53영수30.0생수2
63영수30.0수건2
71영희20.0치약3
84수민31.0생수2
99NaNNaN케이스1
  1. full outer join

pd.merge(customer,orders,on=’customer_id’,how=’outer’)

  • left+right 라고 생각하면 편함
customer_idname나이itemquantity
00철수40.0NaNNaN
11영희20.0치약1.0
21영희20.0칫솔2.0
31영희20.0치약3.0
42길동21.0이어폰1.0
52길동21.0헤드셋1.0
62길동21.0수건3.0
73영수30.0생수2.0
83영수30.0수건2.0
94수민31.0생수2.0
105동건18.0NaNNaN
119NaNNaN케이스1.0

index 기준으로 merge

# pd.merge(
#     left,
#     right,
#     how: str = 'inner',
#     on=None,
#     left_on=None,
#     right_on=None,
#     left_index: bool = False,   <-- merge 기준이 index 인지 여부
#     right_index: bool = False,  <-- merge 기준이 index 인지 여부
#     sort: bool = False,
#     suffixes=('_x', '_y'),
#     copy: bool = True,
#     indicator: bool = False,
#     validate=None,
# ) -> 'DataFrame'

cust1 = customer.set_index(’customer_id’)

order1 = orders.set_index(’customer_id’)

name나이
customer_id
0철수40
1영희20
2길동21
3영수30
4수민31
5동건18
itemquantity
customer_id
1치약1
1칫솔2
2이어폰1
2헤드셋1
2수건3
3생수2
3수건2
1치약3
4생수2
9케이스1
  • index 이름 이 같으면 굳이 on= 없어도 index 기준으로 merge 가능

pd.merge(cust1,order1,left_index=True,right_index=True)

name나이itemquantity
customer_id
1영희20치약1
1영희20칫솔2
1영희20치약3
2길동21이어폰1
2길동21헤드셋1
2길동21수건3
3영수30생수2
3영수30수건2
4수민31생수2

join() 함수

  • 내부적으로 pd.merge 함수 사용
  • 기본적으로 index 사용하여 left join (이게 디폴트임)
  • 주어진 자료들

cust1

order1

name나이
customer_id
0철수40
1영희20
2길동21
3영수30
4수민31
5동건18
itemquantity
customer_id
1치약1
1칫솔2
2이어폰1
2헤드셋1
2수건3
3생수2
3수건2
1치약3
4생수2
9케이스1
  • cust1.join(order1)
name나이itemquantity
customer_id
0철수40NaN
1영희20치약
1영희20칫솔
1영희20치약
2길동21이어폰
2길동21헤드셋
2길동21수건
3영수30생수
3영수30수건
4수민31생수
5동건18NaN

⇒철수, 동건이가 나온 것을 보아 left outer join

  • cust1.join(order1,how=’inner’)
name나이itemquantity
customer_id
1영희20치약1
1영희20칫솔2
1영희20치약3
2길동21이어폰1
2길동21헤드셋1
2길동21수건3
3영수30생수2
3영수30수건2
4수민31생수2
profile
어리둥절 빙글빙글 돌아가는 코딩세상~

0개의 댓글