one-hot encoding
범주형 데이터 전처리
- 범주형 데이터는 분석단계에서 계산이 어렵기 때문에 숫자형으로 변경이 필요
- 범주형 데이터의 각 범주를 column레벨로 변경
- 해당 범주에 해당하면 1, 아니면 0으로 채우는 인코딩 기법
- pandas.get_dummies 함수 사용
- columns= 파라미터로 one-hot encoding 컬럼으로 만들어질 컬럼들을 지정해줄 수 있다.
pd.get_dummies(df,columns=['Pclass','Sex','Embarked']
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 속성
get_group
grouped_pclass.get_group(1)
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')
| PassengerId | Name | Sex |
|---|
| Pclass | | | |
| 3 | 1 | Braund, Mr. Owen Harris | male |
| Pclass | Sex | PassengerId | Survived | Name |
|---|
| 0 | 3 | male | 1 | 0 | Braund, Mr. Owen Harris |
| 1 | 1 | female | 2 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... |
| 2 | 3 | female | 3 | 1 | Heikkinen, Miss. Laina |
groupby(함수)
- 함수의 매개변수는 index
- 함수가 리턴하는 값이 grouping 기준이 된다
나이대별 생존률 구하기
df.set_index('Age')
| Age | PassengerId | Survived | Pclass | Name | | | | | | | |
|---|
| 22.0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | | | | | | |
..
- 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])
| | sum | mean |
|---|
| Pclass | Sex | | |
| 1 | female | 44106 | 469.212766 |
| male | 55599 | 455.729508 |
| 2 | female | 33676 | 443.105263 |
| male | 48380 | 447.962963 |
| 3 | female | 57561 | 399.729167 |
| male | 158064 | 455.515850 |
sort_values(), sort_index()
값 기준 정렬, index 기준 정렬
- by= 정렬기준
- 컬럼면, 컬럼들의 리스트
- Pclass 1-2-3 오름차순 정렬
df.sort_values(by='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.0 | 50.0 | 100.0 | 200.0 | 200.0 | 10.0 | 50.0 | 80.0 | 10.0 | 20.0 |
| 부산 | NaN | NaN | NaN | 100.0 | 200.0 | NaN | NaN | NaN | 30.0 | |
pd.pivot_table()
- 기능적으로 pivot 과 동일
- pivot과의 차이점
- 중복되는 모호한 값이 있을 경우 aggregation함수 사용하여 값 채움
stack & unstack
- stack: 컬럼 레벨에서 인덱스 레벨(row)로 dataframe 변경
- unstack: 인덱스 레벨에서 컬럼 레벨로 dataframe 변경
| 지역 | 요일 | 강수량 |
|---|
| 0 | 서울 | 월요일 | 100 |
| 1 | 서울 | 화요일 | 80 |
| 2 | 서울 | 수요일 | 1000 |
| 3 | 경기 | 월요일 | 200 |
| 4 | 경기 | 화요일 | 200 |
new_df = df.set_index(['지역','요일'])
new_df
| | 강수량 | 강수확률 |
|---|
| 지역 | 요일 | | |
| 서울 | 월요일 | 100 | 80 |
| 화요일 | 80 | 70 |
| 수요일 | 1000 | 90 |
| 경기 | 월요일 | 200 | 10 |
| 화요일 | 200 | 20 |
| 부산 | 월요일 | 100 | 30 |
| 서울 | 목요일 | 50 | 50 |
| 금요일 | 100 | 90 |
| 부산 | 화요일 | 200 | 20 |
| 경기 | 수요일 | 100 | 80 |
| 목요일 | 50 | 50 |
| 금요일 | 100 | 10 |
unstack() : index(row) →column
- new_df 의 경우 지역의 인덱스 레벨=0, 오른쪽 끝 인덱스 ‘요일’
new_df.unstack()
| 강수량 | | | | | 강수확률 | | | | |
|---|
| 요일 | 금요일 | 목요일 | 수요일 | 월요일 | 화요일 | 금요일 | 목요일 | 수요일 | 월요일 |
| 지역 | | | | | | | | | |
| 경기 | 100.0 | 50.0 | 100.0 | 200.0 | 200.0 | 10.0 | 50.0 | 80.0 | 10.0 |
| 부산 | NaN | NaN | NaN | 100.0 | 200.0 | NaN | NaN | NaN | 30.0 |
| 서울 | 100.0 | 50.0 | 1000.0 | 100.0 | 80.0 | 90.0 | 50.0 | 90.0 | 80.0 |
stack() : column→index(row)
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
| key1 | value1 |
|---|
| 0 | 0 | 0.299311 |
| 1 | 1 | 1.254077 |
| 2 | 2 | -0.731377 |
| 3 | 3 | -1.906425 |
| 4 | 4 | 1.377054 |
| 5 | 5 | 0.015715 |
| 6 | 6 | 0.591958 |
| 7 | 7 | 1.400798 |
| 8 | 8 | -0.220856 |
| 9 | 9 | 2.383409 |
df2
| key1 | value1 |
|---|
| 0 | 0 | 0.301718 |
| 1 | 1 | -1.734791 |
| 2 | 2 | 0.785245 |
| 3 | 3 | 2.621160 |
| 4 | 4 | -0.722719 |
| 5 | 5 | 0.648751 |
| 6 | 6 | -0.089522 |
| 7 | 7 | -0.244356 |
| 8 | 8 | 1.581203 |
| 9 | 9 | -0.345149 |
pd.concat([df1,df2])
| key1 | value1 |
|---|
| 0 | 0 | 0.299311 |
| 1 | 1 | 1.254077 |
| 2 | 2 | -0.731377 |
| 3 | 3 | -1.906425 |
| 4 | 4 | 1.377054 |
| 5 | 5 | 0.015715 |
| 6 | 6 | 0.591958 |
| 7 | 7 | 1.400798 |
| 8 | 8 | -0.220856 |
| 9 | 9 | 2.383409 |
| 0 | 0 | 0.301718 |
| 1 | 1 | -1.734791 |
| 2 | 2 | 0.785245 |
| 3 | 3 | 2.621160 |
| 4 | 4 | -0.722719 |
| 5 | 5 | 0.648751 |
| 6 | 6 | -0.089522 |
| 7 | 7 | -0.244356 |
| 8 | 8 | 1.581203 |
| 9 | 9 | -0.345149 |
pd.concat([df1,df2],axis=1)
| key1 | value1 | key1 | value1 |
|---|
| 0 | 0 | 0.299311 | 0 | 0.301718 |
| 1 | 1 | 1.254077 | 1 | -1.734791 |
| 2 | 2 | -0.731377 | 2 | 0.785245 |
| 3 | 3 | -1.906425 | 3 | 2.621160 |
| 4 | 4 | 1.377054 | 4 | -0.722719 |
| 5 | 5 | 0.015715 | 5 | 0.648751 |
| 6 | 6 | 0.591958 | 6 | -0.089522 |
| 7 | 7 | 1.400798 | 7 | -0.244356 |
| 8 | 8 | -0.220856 | 8 | 1.581203 |
| 9 | 9 | 2.383409 | 9 | -0.345149 |
⇒병합 시 서로에게 없는 컬럼값은 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_id | name | 나이 |
|---|
| 0 | 0 | 철수 | 40 |
| 1 | 1 | 영희 | 20 |
| 2 | 2 | 길동 | 21 |
| 3 | 3 | 영수 | 30 |
| 4 | 4 | 수민 | 31 |
| 5 | 5 | 동건 | 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_id | item | quantity |
|---|
| 0 | 1 | 치약 | 1 |
| 1 | 1 | 칫솔 | 2 |
| 2 | 2 | 이어폰 | 1 |
| 3 | 2 | 헤드셋 | 1 |
| 4 | 2 | 수건 | 3 |
| 5 | 3 | 생수 | 2 |
| 6 | 3 | 수건 | 2 |
| 7 | 1 | 치약 | 3 |
| 8 | 4 | 생수 | 2 |
| 9 | 9 | 케이스 | 1 |
pd.merge(customer,orders,on=’customer_id’)
| customer_id | name | 나이 | item | quantity |
|---|
| 0 | 1 | 영희 | 20 | 치약 | 1 |
| 1 | 1 | 영희 | 20 | 칫솔 | 2 |
| 2 | 1 | 영희 | 20 | 치약 | 3 |
| 3 | 2 | 길동 | 21 | 이어폰 | 1 |
| 4 | 2 | 길동 | 21 | 헤드셋 | 1 |
| 5 | 2 | 길동 | 21 | 수건 | 3 |
| 6 | 3 | 영수 | 30 | 생수 | 2 |
| 7 | 3 | 영수 | 30 | 수건 | 2 |
| 8 | 4 | 수민 | 31 | 생수 | 2 |
- customer_id 컬럼을 기준으로 merge 됨
- 기본적으로 inner join 이기에 조건에 맞지 않으면 빠진다(how=”inner”)
- customer 테이블의 동건,철수 빠졌고 orders 테이블에서는 9번 customer가 주문한 내용이 빠짐
- left outer join
pd.merge(customer,orders,on=’customer_id’,how=’left’)
- customer 가 left 이다. 즉, 철수,동건이 보인다.
| customer_id | name | 나이 | item | quantity |
|---|
| 0 | 0 | 철수 | 40 | NaN | NaN |
| 1 | 1 | 영희 | 20 | 치약 | 1.0 |
| 2 | 1 | 영희 | 20 | 칫솔 | 2.0 |
| 3 | 1 | 영희 | 20 | 치약 | 3.0 |
| 4 | 2 | 길동 | 21 | 이어폰 | 1.0 |
| 5 | 2 | 길동 | 21 | 헤드셋 | 1.0 |
| 6 | 2 | 길동 | 21 | 수건 | 3.0 |
| 7 | 3 | 영수 | 30 | 생수 | 2.0 |
| 8 | 3 | 영수 | 30 | 수건 | 2.0 |
| 9 | 4 | 수민 | 31 | 생수 | 2.0 |
| 10 | 5 | 동건 | 18 | NaN | NaN |
- right outer join
pd.merge(customer,orders,on=’customer_id’,how=’right’)
| customer_id | name | 나이 | item | quantity |
|---|
| 0 | 1 | 영희 | 20.0 | 치약 | 1 |
| 1 | 1 | 영희 | 20.0 | 칫솔 | 2 |
| 2 | 2 | 길동 | 21.0 | 이어폰 | 1 |
| 3 | 2 | 길동 | 21.0 | 헤드셋 | 1 |
| 4 | 2 | 길동 | 21.0 | 수건 | 3 |
| 5 | 3 | 영수 | 30.0 | 생수 | 2 |
| 6 | 3 | 영수 | 30.0 | 수건 | 2 |
| 7 | 1 | 영희 | 20.0 | 치약 | 3 |
| 8 | 4 | 수민 | 31.0 | 생수 | 2 |
| 9 | 9 | NaN | NaN | 케이스 | 1 |
- full outer join
pd.merge(customer,orders,on=’customer_id’,how=’outer’)
| customer_id | name | 나이 | item | quantity |
|---|
| 0 | 0 | 철수 | 40.0 | NaN | NaN |
| 1 | 1 | 영희 | 20.0 | 치약 | 1.0 |
| 2 | 1 | 영희 | 20.0 | 칫솔 | 2.0 |
| 3 | 1 | 영희 | 20.0 | 치약 | 3.0 |
| 4 | 2 | 길동 | 21.0 | 이어폰 | 1.0 |
| 5 | 2 | 길동 | 21.0 | 헤드셋 | 1.0 |
| 6 | 2 | 길동 | 21.0 | 수건 | 3.0 |
| 7 | 3 | 영수 | 30.0 | 생수 | 2.0 |
| 8 | 3 | 영수 | 30.0 | 수건 | 2.0 |
| 9 | 4 | 수민 | 31.0 | 생수 | 2.0 |
| 10 | 5 | 동건 | 18.0 | NaN | NaN |
| 11 | 9 | NaN | NaN | 케이스 | 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 |
| item | quantity |
|---|
| 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 | 나이 | item | quantity |
|---|
| 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 |
| item | quantity |
|---|
| customer_id | | |
| 1 | 치약 | 1 |
| 1 | 칫솔 | 2 |
| 2 | 이어폰 | 1 |
| 2 | 헤드셋 | 1 |
| 2 | 수건 | 3 |
| 3 | 생수 | 2 |
| 3 | 수건 | 2 |
| 1 | 치약 | 3 |
| 4 | 생수 | 2 |
| 9 | 케이스 | 1 |
| name | 나이 | item | quantity |
|---|
| customer_id | | | |
| 0 | 철수 | 40 | NaN |
| 1 | 영희 | 20 | 치약 |
| 1 | 영희 | 20 | 칫솔 |
| 1 | 영희 | 20 | 치약 |
| 2 | 길동 | 21 | 이어폰 |
| 2 | 길동 | 21 | 헤드셋 |
| 2 | 길동 | 21 | 수건 |
| 3 | 영수 | 30 | 생수 |
| 3 | 영수 | 30 | 수건 |
| 4 | 수민 | 31 | 생수 |
| 5 | 동건 | 18 | NaN |
⇒철수, 동건이가 나온 것을 보아 left outer join
- cust1.join(order1,how=’inner’)
| name | 나이 | item | quantity |
|---|
| 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 |