Group by
db를 다룰때 group by를 쓰곤 했는데, pandas에도 비슷한 기능이 있다.
다음과 같은 data frame을 변형해본다.
# data from:
data = {'group': ['A', 'A', 'A', 'D', 'c',
'b', 'B', 'C', 'D', 'D', 'd', 'C'],
'age': [20,25,23,21,24,25,21,28,26,25,23,21],
'num':[123,45,342,324,35,4523,34,452,3452,324,8567,563]}
df = pd.DataFrame(data)
df
groupby 함수를 아래와 같이쓸 수 있다.
df.groupby("group")["num"].sum()
''' 결과
group
A 510
B 34
C 1015
D 4100
b 4523
c 35
d 8567
Name: num, dtype: int64
'''
# 여러개도 가능하다.
h = df.groupby(["group", 'age'])["num"].sum()
''' 결과
group age
A 20 123
23 342
25 45
B 21 34
C 21 563
28 452
D 21 324
25 324
26 3452
b 25 4523
c 24 35
d 23 8567
Name: num, dtype: int64
'''
# 새로 생성된 h는 Series이다.
type(h)
'''
pandas.core.series.Series
'''
# index는 여러개로 잡혀있다.
h.index
'''
MultiIndex([('A', 20),
('A', 23),
('A', 25),
('B', 21),
('C', 21),
('C', 28),
('D', 21),
('D', 25),
('D', 26),
('b', 25),
('c', 24),
('d', 23)],
names=['group', 'age'])
'''
새로 생성한 series을 가지고 이것저것 해볼 수 있다.
- unstack: 그룹 풀기
- swaplevel: 그룹 순서 바꾸기
- sum(level=lv): lv번째 인덱스로 묶어 더하기 *deprecated. -> groupby(level=lv).sum()을 쓰길바람.
unh = h.unstack()
'''
age 20 21 23 24 25 26 28
group
A 123.0 NaN 342.0 NaN 45.0 NaN NaN
B NaN 34.0 NaN NaN NaN NaN NaN
C NaN 563.0 NaN NaN NaN NaN 452.0
D NaN 324.0 NaN NaN 324.0 3452.0 NaN
b NaN NaN NaN NaN 4523.0 NaN NaN
c NaN NaN NaN 35.0 NaN NaN NaN
d NaN NaN 8567.0 NaN NaN NaN NaN
'''
unh.index
''' 원래의 range index가 아닌 group이 index로 잡히는 것을 볼 수 있다.
Index(['A', 'B', 'C', 'D', 'b', 'c', 'd'], dtype='object', name='group')
'''
h.swaplevel()
''' group age 순을 age group 순으로 바꿨다.
age group
20 A 123
23 A 342
25 A 45
21 B 34
C 563
28 C 452
21 D 324
25 D 324
26 D 3452
25 b 4523
24 c 35
23 d 8567
Name: num, dtype: int64
'''
h.sum(level=0)
''' 첫번째 index로 묶는다.
group
A 510
B 34
C 1015
D 4100
b 4523
c 35
d 8567
Name: num, dtype: int64
'''
h.groupby(level=1).sum()
''' h.sum(level=1)과 동일하나, pandas는 더 직관적인 groupby를 쓰도록 하고 있다.
age
20 123
21 921
23 8909
24 35
25 4892
26 3452
28 452
Name: num, dtype: int64
'''
grouped 상태 사용하기
# groupby만 쓴다면, grouped 상태라고 하며 generator와 같다.
grouped = df.groupby('group')
# for문에 key: value 값으로 그룹별로 순회할 수 있다.
for name,group in grouped:
print(name)
print(type(group))
'''
A
<class 'pandas.core.frame.DataFrame'>
B
<class 'pandas.core.frame.DataFrame'>
C
<class 'pandas.core.frame.DataFrame'>
D
<class 'pandas.core.frame.DataFrame'>
b
<class 'pandas.core.frame.DataFrame'>
c
<class 'pandas.core.frame.DataFrame'>
d
<class 'pandas.core.frame.DataFrame'>
'''
# Aggregation도 쓸 수 있다.
grouped.agg(min) # 각각의 그룹 dataframe에 대해 가장 큰 값을 뽑아냄
'''
age num
group
A 20 45 # 하나의 컬럼이 아닌 가장 작은 age와 num임.
B 21 34
C 21 452
D 21 324
b 25 4523
c 24 35
d 23 8567
'''
# 그룹별 각 그룹 내 컬럼의 값을 변경하는 것.
grouped.transform(lambda x: x.min())
'''
age num
0 20 45
1 20 45
2 20 45
3 21 324
4 24 35
5 25 4523
6 21 34
7 21 452
8 21 324
9 21 324
10 23 8567
11 21 452
'''
# 그룹을 필터링 할 수도 있다.
# having과 같은 느낌의 filter 함수.
grouped.filter(lambda x: x["num"].max() > 1000)
'''
group age num
3 D 21 324
5 b 25 4523
8 D 26 3452
9 D 25 324
10 d 23 8567
'''
기타 도움 되었던 것들.
value_counts
# 컬럼의 값들의 빈도룰 반환하는 함수.
df[컬럼 이름].value_counts()
'''
칼럼1 200
칼럼2 100
Name 컬럼 이름, dtype: float64
'''
# 빈도를 비율로 구하고 싶다면 normalize값을 주면 된다.
df[컬럼 이름].value_counts(normalize=True)
'''
칼럼1 0.6666
칼럼2 0.3333
Name 컬럼 이름, dtype: float64
'''
pd.cut
# pd.cut은 이름에 걸맞게 연속적인 값들을 특정한 값으로 분류할때 쓰인다.
# 예를들면 아래의 경우 (0, 10], (10, 20], (20, 30] 순.
categories = pd.cut(df[컬럼], bins=[0, 10, 20, 30, 40])
회고
pandas에서 제공하는 기능이 많아 이번은 어려웠다.
앞으로 많이 사용해보며 익숙해져야 겠다.
'프로그래밍 > 부스트캠프 AI' 카테고리의 다른 글
DKT - EDA 해보기 (1) | 2023.05.06 |
---|---|
[level1] preprocess 최적화 (캐싱) (0) | 2023.04.16 |
Day 5 - CNN, RNN (0) | 2023.03.11 |
Day 4 - AI Basic (0) | 2023.03.09 |
Day 2 - 파이썬 oop 및 데이터 다루기 (0) | 2023.03.07 |