Data analysis 5 (pandas)
Pandas (3)
8. 데이터 정제 및 준비
import pandas as pd
import numpy as np
8.2 데이터 변형
- 중복 제거하기
data = pd.DataFrame({'k1' : ['one', 'two'] * 3 + ['two'],
'k2' : [1, 1, 2, 3, 3, 4, 4]} )
data
k1 | k2 | |
---|---|---|
0 | one | 1 |
1 | two | 1 |
2 | one | 2 |
3 | two | 3 |
4 | one | 3 |
5 | two | 4 |
6 | two | 4 |
data.duplicated(keep='first') # keep='first' (기본값값)
0 False
1 False
2 False
3 False
4 False
5 False
6 True
dtype: bool
data.duplicated(keep='last')
0 False
1 False
2 False
3 False
4 False
5 True
6 False
dtype: bool
data.duplicated(['k1'])
0 False
1 False
2 True
3 True
4 True
5 True
6 True
dtype: bool
# 중복 삭제
data.drop_duplicates()
k1 | k2 | |
---|---|---|
0 | one | 1 |
1 | two | 1 |
2 | one | 2 |
3 | two | 3 |
4 | one | 3 |
5 | two | 4 |
# k1 열 기준으로 삭제제
data.drop_duplicates(['k1'])
k1 | k2 | |
---|---|---|
0 | one | 1 |
1 | two | 1 |
data.drop_duplicates(['k1'], keep='last')
k1 | k2 | |
---|---|---|
4 | one | 3 |
6 | two | 4 |
data['v1'] = range(7)
data
k1 | k2 | v1 | |
---|---|---|---|
0 | one | 1 | 0 |
1 | two | 1 | 1 |
2 | one | 2 | 2 |
3 | two | 3 | 3 |
4 | one | 3 | 4 |
5 | two | 4 | 5 |
6 | two | 4 | 6 |
data.duplicated()
0 False
1 False
2 False
3 False
4 False
5 False
6 False
dtype: bool
data.drop_duplicates(['k1', 'k2'])
k1 | k2 | v1 | |
---|---|---|---|
0 | one | 1 | 0 |
1 | two | 1 | 1 |
2 | one | 2 | 2 |
3 | two | 3 | 3 |
4 | one | 3 | 4 |
5 | two | 4 | 5 |
- 함수나 매핑을 이용해서 데이터 변형하기
data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon',
'Pastrami', 'corned beef', 'Bacon',
'pastrami', 'honey ham', 'nova lox'],
'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
data
food | ounces | |
---|---|---|
0 | bacon | 4.0 |
1 | pulled pork | 3.0 |
2 | bacon | 12.0 |
3 | Pastrami | 6.0 |
4 | corned beef | 7.5 |
5 | Bacon | 8.0 |
6 | pastrami | 3.0 |
7 | honey ham | 5.0 |
8 | nova lox | 6.0 |
meat_to_animal = {
'bacon': 'pig',
'pulled pork': 'pig',
'pastrami': 'cow',
'corned beef': 'cow',
'honey ham': 'pig',
'nova lox': 'salmon'
}
"ABC".lower()
'abc'
lowercased = data['food'].str.lower()
lowercased
0 bacon
1 pulled pork
2 bacon
3 pastrami
4 corned beef
5 bacon
6 pastrami
7 honey ham
8 nova lox
Name: food, dtype: object
data['animal']= lowercased.map(meat_to_animal)
- 값 치환하기
data = pd.Series([1, -999, 2, -999, -1000, 3])
data
0 1
1 -999
2 2
3 -999
4 -1000
5 3
dtype: int64
data.replace(-999, np.nan)
0 1.0
1 NaN
2 2.0
3 NaN
4 -1000.0
5 3.0
dtype: float64
data.replace([-999, -1000], np.nan)
0 1.0
1 NaN
2 2.0
3 NaN
4 NaN
5 3.0
dtype: float64
data.replace({-999:np.nan, -1000:0})
0 1.0
1 NaN
2 2.0
3 NaN
4 0.0
5 3.0
dtype: float64
- 축 색인 이름 바꾸기
data = pd.DataFrame(np.arange(12).reshape(3, 4),
index=['Ohio', 'Colorado', 'New York'],
columns=['one', 'two', 'three', 'four'])
data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
New York | 8 | 9 | 10 | 11 |
data.index
Index(['Ohio', 'Colorado', 'New York'], dtype='object')
def trans_upper(x):
return x.upper()
data.index.map(trans_upper)
Index(['OHIO', 'COLORADO', 'NEW YORK'], dtype='object')
data.index.map(lambda x:x.upper())
Index(['OHIO', 'COLORADO', 'NEW YORK'], dtype='object')
data.index.map(lambda x:x.title())
Index(['Ohio', 'Colorado', 'New York'], dtype='object')
data.rename(index = str.lower, columns= str.title) # rename 함수의 index/columns 에 함수를 적용할 수 있음
One | Two | Three | Four | |
---|---|---|---|---|
ohio | 0 | 1 | 2 | 3 |
colorado | 4 | 5 | 6 | 7 |
new york | 8 | 9 | 10 | 11 |
data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
New York | 8 | 9 | 10 | 11 |
- 벡터화된 문자열 함수
data = {'Dave':'dave@gmail.com',
'Steve': 'steve@gmail.com',
'Rob':'rob@gmail.com',
'Wes':np.nan,
'Puppy':'p',
'Number':'123'}
sr_data= pd.Series(data)
sr_data
Dave dave@gmail.com
Steve steve@gmail.com
Rob rob@gmail.com
Wes NaN
Puppy p
Number 123
dtype: object
'dave@gmail.com'.upper()
'DAVE@GMAIL.COM'
sr_data.str.upper()
Dave DAVE@GMAIL.COM
Steve STEVE@GMAIL.COM
Rob ROB@GMAIL.COM
Wes NaN
Puppy P
Number 123
dtype: object
'123'.isnumeric()
True
'dave@gmail.com'.isnumeric()
False
sr_data.str.isnumeric()
Dave False
Steve False
Rob False
Wes NaN
Puppy False
Number True
dtype: object
sr_data.str.isalpha()
Dave False
Steve False
Rob False
Wes NaN
Puppy True
Number False
dtype: object
sr_data.str.contains('gmail')
Dave True
Steve True
Rob True
Wes NaN
Puppy False
Number False
dtype: object
- 데이터 구간 분할
# 수치데이터(양적데이터) -> 범주형데이터(질적데이터터)
ages = [18, 20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
ages
[18, 20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
cats = pd.cut(ages, 4) # 범위 안에서 4구간으로 나눌 수 있음음
cats
bins= [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins) # bins를 통해 원하는 구간을 지정할 수 있음음
cats
bins= [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins, include_lowest=True) # 가장 작은수가 포함시키는 옵션션
cats
[(17.999, 25.0], (17.999, 25.0], (17.999, 25.0], (17.999, 25.0], (25.0, 35.0], ..., (25.0, 35.0], (60.0, 100.0], (35.0, 60.0], (35.0, 60.0], (25.0, 35.0]]
Length: 13
Categories (4, interval[float64, right]): [(17.999, 25.0] < (25.0, 35.0] < (35.0, 60.0] <
(60.0, 100.0]]
cats = pd.cut(ages, bins, include_lowest=True, labels=['youth', 'youngadult', 'middleages', 'senior'])
cats
['youth', 'youth', 'youth', 'youth', 'youngadult', ..., 'youngadult', 'senior', 'middleages', 'middleages', 'youngadult']
Length: 13
Categories (4, object): ['youth' < 'youngadult' < 'middleages' < 'senior']
cats.value_counts() # 범주형 데이터로 변환되었기 때문에 빈도수도 카운트 할 수 있음음
youth 6
youngadult 3
middleages 3
senior 1
dtype: int64
cats = pd.cut(ages, 4) # 범위 안에서 4구간으로 나눌 수 있음
cats.value_counts()
(17.957, 28.75] 7
(28.75, 39.5] 3
(39.5, 50.25] 2
(50.25, 61.0] 1
dtype: int64
cats = pd.qcut(ages, 4) # 4구간안에 동일한 양이 들어가도록 분할
cats.value_counts()
(17.999, 22.0] 4
(22.0, 27.0] 3
(27.0, 37.0] 3
(37.0, 61.0] 3
dtype: int64
- 특이값(바깥값, outlier) 찾고 제외하기
data = pd.DataFrame(np.random.randn(1000, 4))
data.describe()
0 | 1 | 2 | 3 | |
---|---|---|---|---|
count | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 |
mean | -0.073027 | -0.039069 | -0.025754 | -0.033337 |
std | 1.019392 | 0.991063 | 0.979328 | 0.977642 |
min | -4.479930 | -3.135338 | -3.763374 | -3.288864 |
25% | -0.761516 | -0.672036 | -0.667080 | -0.659778 |
50% | -0.077066 | -0.033668 | -0.001968 | -0.003941 |
75% | 0.637678 | 0.637472 | 0.604178 | 0.677430 |
max | 2.931344 | 3.449874 | 3.090328 | 3.284176 |
# 3보다 큰 값을 특잇값(바깥값, outlier)로 가정하고, 해당되는 값을 3으로 치환환
data > 3
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | False | False | False | False |
1 | False | False | False | False |
2 | False | False | False | False |
3 | False | False | False | False |
4 | False | False | False | False |
... | ... | ... | ... | ... |
995 | False | False | False | False |
996 | False | False | False | False |
997 | False | False | False | False |
998 | False | False | False | False |
999 | False | False | False | False |
1000 rows × 4 columns
(data > 3).any(axis=1) # 열축을 따라서 True 값이 하나라도 있는지 확인
0 False
1 False
2 False
3 False
4 False
...
995 False
996 False
997 False
998 False
999 False
Length: 1000, dtype: bool
(data > 3).any(axis=1).sum()
3
data[(data > 3).any(axis=1)]
0 | 1 | 2 | 3 | |
---|---|---|---|---|
84 | -1.034572 | 3.449874 | 1.025486 | -0.294470 |
704 | -2.300875 | -0.342656 | 3.090328 | 0.381429 |
860 | -1.471528 | 0.187926 | 0.499964 | 3.284176 |
data[data > 3] = 3
data.describe()
0 | 1 | 2 | 3 | |
---|---|---|---|---|
count | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 |
mean | -0.073027 | -0.039519 | -0.025844 | -0.033622 |
std | 1.019392 | 0.989579 | 0.979044 | 0.976717 |
min | -4.479930 | -3.135338 | -3.763374 | -3.288864 |
25% | -0.761516 | -0.672036 | -0.667080 | -0.659778 |
50% | -0.077066 | -0.033668 | -0.001968 | -0.003941 |
75% | 0.637678 | 0.637472 | 0.604178 | 0.677430 |
max | 2.931344 | 3.000000 | 3.000000 | 3.000000 |
- 더미변수 계산하기(one-hot encoding)
df = pd.DataFrame({'fruit' : ['apple', 'apple', 'pear', 'peach', 'pear'],
'data' : range(5)})
df
fruit | data | |
---|---|---|
0 | apple | 0 |
1 | apple | 1 |
2 | pear | 2 |
3 | peach | 3 |
4 | pear | 4 |
dummies = pd.get_dummies(df['fruit'], prefix='fruit')
dummies
fruit_apple | fruit_peach | fruit_pear | |
---|---|---|---|
0 | 1 | 0 | 0 |
1 | 1 | 0 | 0 |
2 | 0 | 0 | 1 |
3 | 0 | 1 | 0 |
4 | 0 | 0 | 1 |
df[['data']]
data | |
---|---|
0 | 0 |
1 | 1 |
2 | 2 |
3 | 3 |
4 | 4 |
pd.concat([dummies, df[['data']]], axis=1)
fruit_apple | fruit_peach | fruit_pear | data | |
---|---|---|---|---|
0 | 1 | 0 | 0 | 0 |
1 | 1 | 0 | 0 | 1 |
2 | 0 | 0 | 1 | 2 |
3 | 0 | 1 | 0 | 3 |
4 | 0 | 0 | 1 | 4 |
9. 데이터 재구성
9.1 계층적 색인
data = pd.Series(np.random.randn(9),
index = [['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 3, 1, 2, 2, 3]])
data
a 1 0.759512
2 2.266371
3 -0.547481
b 1 0.900922
3 -1.452136
c 1 0.321089
2 -0.123710
d 2 0.133820
3 -1.512736
dtype: float64
data.index
MultiIndex([('a', 1),
('a', 2),
('a', 3),
('b', 1),
('b', 3),
('c', 1),
('c', 2),
('d', 2),
('d', 3)],
)
data.loc['b']
1 0.900922
3 -1.452136
dtype: float64
data.loc['b' : 'c'] # 라벨 색인
b 1 0.900922
3 -1.452136
c 1 0.321089
2 -0.123710
dtype: float64
data.iloc[3: 7] # 정수 색인
b 1 0.900922
3 -1.452136
c 1 0.321089
2 -0.123710
dtype: float64
data # index가 쌓여있는 상태(stack)
a 1 0.759512
2 2.266371
3 -0.547481
b 1 0.900922
3 -1.452136
c 1 0.321089
2 -0.123710
d 2 0.133820
3 -1.512736
dtype: float64
unstacked_data = data.unstack()
unstacked_data
1 | 2 | 3 | |
---|---|---|---|
a | 0.759512 | 2.266371 | -0.547481 |
b | 0.900922 | NaN | -1.452136 |
c | 0.321089 | -0.123710 | NaN |
d | NaN | 0.133820 | -1.512736 |
stacked_data = unstacked_data.stack()
stacked_data
a 1 0.759512
2 2.266371
3 -0.547481
b 1 0.900922
3 -1.452136
c 1 0.321089
2 -0.123710
d 2 0.133820
3 -1.512736
dtype: float64
stacked_data.unstack()
1 | 2 | 3 | |
---|---|---|---|
a | 0.759512 | 2.266371 | -0.547481 |
b | 0.900922 | NaN | -1.452136 |
c | 0.321089 | -0.123710 | NaN |
d | NaN | 0.133820 | -1.512736 |
unstacked_data.reset_index()
index | 1 | 2 | 3 | |
---|---|---|---|---|
0 | a | 0.759512 | 2.266371 | -0.547481 |
1 | b | 0.900922 | NaN | -1.452136 |
2 | c | 0.321089 | -0.123710 | NaN |
3 | d | NaN | 0.133820 | -1.512736 |
stacked_data.reset_index()
level_0 | level_1 | 0 | |
---|---|---|---|
0 | a | 1 | 0.759512 |
1 | a | 2 | 2.266371 |
2 | a | 3 | -0.547481 |
3 | b | 1 | 0.900922 |
4 | b | 3 | -1.452136 |
5 | c | 1 | 0.321089 |
6 | c | 2 | -0.123710 |
7 | d | 2 | 0.133820 |
8 | d | 3 | -1.512736 |
9.2 데이터 합치기
-
데이터베이스 스타일로 DataFrame 합치기
-
inner join
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df2 = pd.DataFrame({'key': ['a', 'b', 'd'],
'data2': range(3)})
df1
key | data1 | |
---|---|---|
0 | b | 0 |
1 | b | 1 |
2 | a | 2 |
3 | c | 3 |
4 | a | 4 |
5 | a | 5 |
6 | b | 6 |
df2
key | data2 | |
---|---|---|
0 | a | 0 |
1 | b | 1 |
2 | d | 2 |
pd.merge(df1, df2, on='key', how='inner')
key | data1 | data2 | |
---|---|---|---|
0 | b | 0 | 1 |
1 | b | 1 | 1 |
2 | b | 6 | 1 |
3 | a | 2 | 0 |
4 | a | 4 | 0 |
5 | a | 5 | 0 |
# 위의 merge 함수 사용법은 아래 query문과 같음
# SELECT a.key, data1, data2
# FROM df1 a
# INNER JOIN df2
# ON a.key = b.key;
pd.merge(df1, df2, on='key') # how='inner'가 기본값값
key | data1 | data2 | |
---|---|---|---|
0 | b | 0 | 1 |
1 | b | 1 | 1 |
2 | b | 6 | 1 |
3 | a | 2 | 0 |
4 | a | 4 | 0 |
5 | a | 5 | 0 |
df3 = pd.DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1': range(7)})
df4 = pd.DataFrame({'rkey': ['a', 'b', 'd'], 'data2': range(3)})
df3
lkey | data1 | |
---|---|---|
0 | b | 0 |
1 | b | 1 |
2 | a | 2 |
3 | c | 3 |
4 | a | 4 |
5 | a | 5 |
6 | b | 6 |
df4
rkey | data2 | |
---|---|---|
0 | a | 0 |
1 | b | 1 |
2 | d | 2 |
pd.merge(df3, df4, left_on= 'lkey', right_on='rkey')
lkey | data1 | rkey | data2 | |
---|---|---|---|---|
0 | b | 0 | b | 1 |
1 | b | 1 | b | 1 |
2 | b | 6 | b | 1 |
3 | a | 2 | a | 0 |
4 | a | 4 | a | 0 |
5 | a | 5 | a | 0 |
# 위의 merge 함수 사용법은 아래 query문과 같음
# SELECT a.lkey, data1, b.rkey, data2
# FROM df3 a
# INNER JOIN df4
# ON a.lkey = b.rkey;
- outer join
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df2 = pd.DataFrame({'key': ['a', 'b', 'd'],
'data2': range(3)})
df1
key | data1 | |
---|---|---|
0 | b | 0 |
1 | b | 1 |
2 | a | 2 |
3 | c | 3 |
4 | a | 4 |
5 | a | 5 |
6 | b | 6 |
df2
key | data2 | |
---|---|---|
0 | a | 0 |
1 | b | 1 |
2 | d | 2 |
pd.merge(df1, df2, on='key', how='left')
key | data1 | data2 | |
---|---|---|---|
0 | b | 0 | 1.0 |
1 | b | 1 | 1.0 |
2 | a | 2 | 0.0 |
3 | c | 3 | NaN |
4 | a | 4 | 0.0 |
5 | a | 5 | 0.0 |
6 | b | 6 | 1.0 |
pd.merge(df1, df2, how='left') # join할 대상의 컬럼명이 같으면 on 파라미터 생략 가능 (natural join)
key | data1 | data2 | |
---|---|---|---|
0 | b | 0 | 1.0 |
1 | b | 1 | 1.0 |
2 | a | 2 | 0.0 |
3 | c | 3 | NaN |
4 | a | 4 | 0.0 |
5 | a | 5 | 0.0 |
6 | b | 6 | 1.0 |
pd.merge(df1, df2, how='right')
key | data1 | data2 | |
---|---|---|---|
0 | a | 2.0 | 0 |
1 | a | 4.0 | 0 |
2 | a | 5.0 | 0 |
3 | b | 0.0 | 1 |
4 | b | 1.0 | 1 |
5 | b | 6.0 | 1 |
6 | d | NaN | 2 |
# df의 위치만 변경시키면 위의 right join과 동일
pd.merge(df2, df1, how='left')
key | data2 | data1 | |
---|---|---|---|
0 | a | 0 | 2.0 |
1 | a | 0 | 4.0 |
2 | a | 0 | 5.0 |
3 | b | 1 | 0.0 |
4 | b | 1 | 1.0 |
5 | b | 1 | 6.0 |
6 | d | 2 | NaN |
pd.merge(df1, df2, how='outer') # left, right를 모두 포함한 join (한쪽에만 있는 데이터도 모두 취함)
key | data1 | data2 | |
---|---|---|---|
0 | b | 0.0 | 1.0 |
1 | b | 1.0 | 1.0 |
2 | b | 6.0 | 1.0 |
3 | a | 2.0 | 0.0 |
4 | a | 4.0 | 0.0 |
5 | a | 5.0 | 0.0 |
6 | c | 3.0 | NaN |
7 | d | NaN | 2.0 |
- 색인 병합하기
left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'], 'value': range(6)})
right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
left1
key | value | |
---|---|---|
0 | a | 0 |
1 | b | 1 |
2 | a | 2 |
3 | a | 3 |
4 | b | 4 |
5 | c | 5 |
right1
group_val | |
---|---|
a | 3.5 |
b | 7.0 |
pd.merge(left1, right1, left_on='key', right_index=True) # inner join
key | value | group_val | |
---|---|---|---|
0 | a | 0 | 3.5 |
2 | a | 2 | 3.5 |
3 | a | 3 | 3.5 |
1 | b | 1 | 7.0 |
4 | b | 4 | 7.0 |
pd.merge(left1, right1, left_on='key', right_index=True, how='outer') # outer join
key | value | group_val | |
---|---|---|---|
0 | a | 0 | 3.5 |
2 | a | 2 | 3.5 |
3 | a | 3 | 3.5 |
1 | b | 1 | 7.0 |
4 | b | 4 | 7.0 |
5 | c | 5 | NaN |
left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]],
index=['a', 'c', 'e'],
columns=['Ohio', 'Nevada'])
right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]],
index=['b', 'c', 'd', 'e'],
columns=['Missouri', 'Alabama'])
left2
Ohio | Nevada | |
---|---|---|
a | 1.0 | 2.0 |
c | 3.0 | 4.0 |
e | 5.0 | 6.0 |
right2
Missouri | Alabama | |
---|---|---|
b | 7.0 | 8.0 |
c | 9.0 | 10.0 |
d | 11.0 | 12.0 |
e | 13.0 | 14.0 |
pd.merge(left2, right2, left_index=True, right_index=True) # inner join
Ohio | Nevada | Missouri | Alabama | |
---|---|---|---|---|
c | 3.0 | 4.0 | 9.0 | 10.0 |
e | 5.0 | 6.0 | 13.0 | 14.0 |
# join 함수는 인덱스 값을 기준으로 조인을 함
# 위의 pd.merge 결과와 동일
left2.join(right2, how='inner') # join 함수의 how='left'가 기본값이므로 inner로 변경경
Ohio | Nevada | Missouri | Alabama | |
---|---|---|---|---|
c | 3.0 | 4.0 | 9.0 | 10.0 |
e | 5.0 | 6.0 | 13.0 | 14.0 |
left1
key | value | |
---|---|---|
0 | a | 0 |
1 | b | 1 |
2 | a | 2 |
3 | a | 3 |
4 | b | 4 |
5 | c | 5 |
right1
group_val | |
---|---|
a | 3.5 |
b | 7.0 |
pd.merge(left1, right1, left_on='key', right_index=True, how='inner')
key | value | group_val | |
---|---|---|---|
0 | a | 0 | 3.5 |
2 | a | 2 | 3.5 |
3 | a | 3 | 3.5 |
1 | b | 1 | 7.0 |
4 | b | 4 | 7.0 |
# join 함수를 사용해서 위와 동일하게 합치려면면
left1.join(right1, on='key', how='inner')
key | value | group_val | |
---|---|---|---|
0 | a | 0 | 3.5 |
2 | a | 2 | 3.5 |
3 | a | 3 | 3.5 |
1 | b | 1 | 7.0 |
4 | b | 4 | 7.0 |
- 축따라 이어붙이기
참고 np.concatenate
arr = np.arange(12).reshape(3, 4)
arr
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
np.concatenate([arr, arr], axis=0) # axis=0 기본값, 0번축을 따라서 이어붙임
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
np.concatenate([arr, arr], axis=1)
array([[ 0, 1, 2, 3, 0, 1, 2, 3],
[ 4, 5, 6, 7, 4, 5, 6, 7],
[ 8, 9, 10, 11, 8, 9, 10, 11]])
s1 = pd.Series([0, 1], index=['a', 'b'])
s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = pd.Series([5, 6], index=['f', 'g'])
s1
a 0
b 1
dtype: int64
s2
c 2
d 3
e 4
dtype: int64
s3
f 5
g 6
dtype: int64
pd.concat([s1, s2, s3], axis=0)
a 0
b 1
c 2
d 3
e 4
f 5
g 6
dtype: int64
pd.concat([s1, s2, s3], axis=1)
0 | 1 | 2 | |
---|---|---|---|
a | 0.0 | NaN | NaN |
b | 1.0 | NaN | NaN |
c | NaN | 2.0 | NaN |
d | NaN | 3.0 | NaN |
e | NaN | 4.0 | NaN |
f | NaN | NaN | 5.0 |
g | NaN | NaN | 6.0 |
df1 = pd.DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd'])
df2 = pd.DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a'])
df1
a | b | c | d | |
---|---|---|---|---|
0 | -1.127909 | 1.862198 | -1.044944 | 1.537435 |
1 | -0.243453 | -0.300529 | 2.783077 | 0.080733 |
2 | -0.917728 | -1.234895 | -0.285104 | 3.605365 |
df2
b | d | a | |
---|---|---|---|
0 | -0.967257 | 0.747703 | 1.636920 |
1 | 0.947134 | -0.868835 | 0.943723 |
pd.concat([df1, df2], axis=0)
a | b | c | d | |
---|---|---|---|---|
0 | -1.127909 | 1.862198 | -1.044944 | 1.537435 |
1 | -0.243453 | -0.300529 | 2.783077 | 0.080733 |
2 | -0.917728 | -1.234895 | -0.285104 | 3.605365 |
0 | 1.636920 | -0.967257 | NaN | 0.747703 |
1 | 0.943723 | 0.947134 | NaN | -0.868835 |
pd.concat([df1, df2], axis=0, ignore_index=True)
a | b | c | d | |
---|---|---|---|---|
0 | -1.127909 | 1.862198 | -1.044944 | 1.537435 |
1 | -0.243453 | -0.300529 | 2.783077 | 0.080733 |
2 | -0.917728 | -1.234895 | -0.285104 | 3.605365 |
3 | 1.636920 | -0.967257 | NaN | 0.747703 |
4 | 0.943723 | 0.947134 | NaN | -0.868835 |
Workshop
- 축따라 이어붙이기
df1 = pd.DataFrame({'a': ['a0', 'a1', 'a2', 'a3'],
'b': ['b0', 'b1', 'b2', 'b3'],
'c': ['c0', 'c1', 'c2', 'c3']},
index=[0, 1, 2, 3])
df2 = pd.DataFrame({'a': ['a2', 'a3', 'a4', 'a5'],
'b': ['b2', 'b3', 'b4', 'b5'],
'c': ['c2', 'c3', 'c4', 'c5'],
'd': ['d2', 'd3', 'd4', 'd5']},
index=[2, 3, 4, 5])
df1
a | b | c | |
---|---|---|---|
0 | a0 | b0 | c0 |
1 | a1 | b1 | c1 |
2 | a2 | b2 | c2 |
3 | a3 | b3 | c3 |
df2
a | b | c | d | |
---|---|---|---|---|
2 | a2 | b2 | c2 | d2 |
3 | a3 | b3 | c3 | d3 |
4 | a4 | b4 | c4 | d4 |
5 | a5 | b5 | c5 | d5 |
# 2개의 데이터프레임을 위, 아래 (행축으로) 이어붙이듯 연결하기
pd.concat([df1, df2], axis=0)
a | b | c | d | |
---|---|---|---|---|
0 | a0 | b0 | c0 | NaN |
1 | a1 | b1 | c1 | NaN |
2 | a2 | b2 | c2 | NaN |
3 | a3 | b3 | c3 | NaN |
2 | a2 | b2 | c2 | d2 |
3 | a3 | b3 | c3 | d3 |
4 | a4 | b4 | c4 | d4 |
5 | a5 | b5 | c5 | d5 |
# 인덱스를 재 설정 (ignore_index 사용용)
pd.concat([df1, df2], axis=0, ignore_index=True)
a | b | c | d | |
---|---|---|---|---|
0 | a0 | b0 | c0 | NaN |
1 | a1 | b1 | c1 | NaN |
2 | a2 | b2 | c2 | NaN |
3 | a3 | b3 | c3 | NaN |
4 | a2 | b2 | c2 | d2 |
5 | a3 | b3 | c3 | d3 |
6 | a4 | b4 | c4 | d4 |
7 | a5 | b5 | c5 | d5 |
# 2개의 데이터프레임을 좌, 우 (열축으로) 이어붙이듯 연결하기
pd.concat([df1, df2], axis=1)
a | b | c | a | b | c | d | |
---|---|---|---|---|---|---|---|
0 | a0 | b0 | c0 | NaN | NaN | NaN | NaN |
1 | a1 | b1 | c1 | NaN | NaN | NaN | NaN |
2 | a2 | b2 | c2 | a2 | b2 | c2 | d2 |
3 | a3 | b3 | c3 | a3 | b3 | c3 | d3 |
4 | NaN | NaN | NaN | a4 | b4 | c4 | d4 |
5 | NaN | NaN | NaN | a5 | b5 | c5 | d5 |
sr = pd.Series(['e0', 'e1', 'e2', 'e3'], name='e')
df1
a | b | c | |
---|---|---|---|
0 | a0 | b0 | c0 |
1 | a1 | b1 | c1 |
2 | a2 | b2 | c2 |
3 | a3 | b3 | c3 |
sr
0 e0
1 e1
2 e2
3 e3
Name: e, dtype: object
# df1과 sr을 좌, 우(열축으로) 이어붙이듯 연결하기
pd.concat([df1, sr], axis=1)
a | b | c | e | |
---|---|---|---|---|
0 | a0 | b0 | c0 | e0 |
1 | a1 | b1 | c1 | e1 |
2 | a2 | b2 | c2 | e2 |
3 | a3 | b3 | c3 | e3 |
- 데이터베이스 스타일로 DataFrame 합치기
df1 = pd.read_excel('./examples/stock price.xlsx')
df2 = pd.read_excel('./examples/stock valuation.xlsx')
df1
id | stock_name | value | price | |
---|---|---|---|---|
0 | 128940 | 한미약품 | 59385.666667 | 421000 |
1 | 130960 | CJ E&M | 58540.666667 | 98900 |
2 | 138250 | 엔에스쇼핑 | 14558.666667 | 13200 |
3 | 139480 | 이마트 | 239230.833333 | 254500 |
4 | 142280 | 녹십자엠에스 | 468.833333 | 10200 |
5 | 145990 | 삼양사 | 82750.000000 | 82000 |
6 | 185750 | 종근당 | 40293.666667 | 100500 |
7 | 192400 | 쿠쿠홀딩스 | 179204.666667 | 177500 |
8 | 199800 | 툴젠 | -2514.333333 | 115400 |
9 | 204210 | 모두투어리츠 | 3093.333333 | 3475 |
df2
id | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|
0 | 130960 | CJ E&M | 6301.333333 | 54068 | 15.695091 | 1.829178 |
1 | 136480 | 하림 | 274.166667 | 3551 | 11.489362 | 0.887074 |
2 | 138040 | 메리츠금융지주 | 2122.333333 | 14894 | 6.313806 | 0.899691 |
3 | 139480 | 이마트 | 18268.166667 | 295780 | 13.931338 | 0.860437 |
4 | 145990 | 삼양사 | 5741.000000 | 108090 | 14.283226 | 0.758627 |
5 | 161390 | 한국타이어 | 5648.500000 | 51341 | 7.453306 | 0.820007 |
6 | 181710 | NHN엔터테인먼트 | 2110.166667 | 78434 | 30.755864 | 0.827447 |
7 | 185750 | 종근당 | 3990.333333 | 40684 | 25.185866 | 2.470259 |
8 | 204210 | 모두투어리츠 | 85.166667 | 5335 | 40.802348 | 0.651359 |
9 | 207940 | 삼성바이오로직스 | 4644.166667 | 60099 | 89.790059 | 6.938551 |
# id 를 조인 조건으로 해서 inner join
pd.merge(df1, df2, on='id', how='inner')
id | stock_name | value | price | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|---|
0 | 130960 | CJ E&M | 58540.666667 | 98900 | CJ E&M | 6301.333333 | 54068 | 15.695091 | 1.829178 |
1 | 139480 | 이마트 | 239230.833333 | 254500 | 이마트 | 18268.166667 | 295780 | 13.931338 | 0.860437 |
2 | 145990 | 삼양사 | 82750.000000 | 82000 | 삼양사 | 5741.000000 | 108090 | 14.283226 | 0.758627 |
3 | 185750 | 종근당 | 40293.666667 | 100500 | 종근당 | 3990.333333 | 40684 | 25.185866 | 2.470259 |
4 | 204210 | 모두투어리츠 | 3093.333333 | 3475 | 모두투어리츠 | 85.166667 | 5335 | 40.802348 | 0.651359 |
pd.merge(df1, df2) # 양쪽 데이터프레임의 컬럼명이 id로 동일하므로 생략 가능
# merge 함수의 how='inner' 가 기본값이므로 생략 가능
id | stock_name | value | price | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|---|
0 | 130960 | CJ E&M | 58540.666667 | 98900 | CJ E&M | 6301.333333 | 54068 | 15.695091 | 1.829178 |
1 | 139480 | 이마트 | 239230.833333 | 254500 | 이마트 | 18268.166667 | 295780 | 13.931338 | 0.860437 |
2 | 145990 | 삼양사 | 82750.000000 | 82000 | 삼양사 | 5741.000000 | 108090 | 14.283226 | 0.758627 |
3 | 185750 | 종근당 | 40293.666667 | 100500 | 종근당 | 3990.333333 | 40684 | 25.185866 | 2.470259 |
4 | 204210 | 모두투어리츠 | 3093.333333 | 3475 | 모두투어리츠 | 85.166667 | 5335 | 40.802348 | 0.651359 |
# id 를 조인 조건으로 해서 outer join
pd.merge(df1, df2, on='id', how='outer')
id | stock_name | value | price | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|---|
0 | 128940 | 한미약품 | 59385.666667 | 421000.0 | NaN | NaN | NaN | NaN | NaN |
1 | 130960 | CJ E&M | 58540.666667 | 98900.0 | CJ E&M | 6301.333333 | 54068.0 | 15.695091 | 1.829178 |
2 | 138250 | 엔에스쇼핑 | 14558.666667 | 13200.0 | NaN | NaN | NaN | NaN | NaN |
3 | 139480 | 이마트 | 239230.833333 | 254500.0 | 이마트 | 18268.166667 | 295780.0 | 13.931338 | 0.860437 |
4 | 142280 | 녹십자엠에스 | 468.833333 | 10200.0 | NaN | NaN | NaN | NaN | NaN |
5 | 145990 | 삼양사 | 82750.000000 | 82000.0 | 삼양사 | 5741.000000 | 108090.0 | 14.283226 | 0.758627 |
6 | 185750 | 종근당 | 40293.666667 | 100500.0 | 종근당 | 3990.333333 | 40684.0 | 25.185866 | 2.470259 |
7 | 192400 | 쿠쿠홀딩스 | 179204.666667 | 177500.0 | NaN | NaN | NaN | NaN | NaN |
8 | 199800 | 툴젠 | -2514.333333 | 115400.0 | NaN | NaN | NaN | NaN | NaN |
9 | 204210 | 모두투어리츠 | 3093.333333 | 3475.0 | 모두투어리츠 | 85.166667 | 5335.0 | 40.802348 | 0.651359 |
10 | 136480 | NaN | NaN | NaN | 하림 | 274.166667 | 3551.0 | 11.489362 | 0.887074 |
11 | 138040 | NaN | NaN | NaN | 메리츠금융지주 | 2122.333333 | 14894.0 | 6.313806 | 0.899691 |
12 | 161390 | NaN | NaN | NaN | 한국타이어 | 5648.500000 | 51341.0 | 7.453306 | 0.820007 |
13 | 181710 | NaN | NaN | NaN | NHN엔터테인먼트 | 2110.166667 | 78434.0 | 30.755864 | 0.827447 |
14 | 207940 | NaN | NaN | NaN | 삼성바이오로직스 | 4644.166667 | 60099.0 | 89.790059 | 6.938551 |
pd.merge(df1, df2, how='outer') # 양쪽 데이터프레임의 컬럼명이 id로 동일하므로 생략 가능
id | stock_name | value | price | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|---|
0 | 128940 | 한미약품 | 59385.666667 | 421000.0 | NaN | NaN | NaN | NaN | NaN |
1 | 130960 | CJ E&M | 58540.666667 | 98900.0 | CJ E&M | 6301.333333 | 54068.0 | 15.695091 | 1.829178 |
2 | 138250 | 엔에스쇼핑 | 14558.666667 | 13200.0 | NaN | NaN | NaN | NaN | NaN |
3 | 139480 | 이마트 | 239230.833333 | 254500.0 | 이마트 | 18268.166667 | 295780.0 | 13.931338 | 0.860437 |
4 | 142280 | 녹십자엠에스 | 468.833333 | 10200.0 | NaN | NaN | NaN | NaN | NaN |
5 | 145990 | 삼양사 | 82750.000000 | 82000.0 | 삼양사 | 5741.000000 | 108090.0 | 14.283226 | 0.758627 |
6 | 185750 | 종근당 | 40293.666667 | 100500.0 | 종근당 | 3990.333333 | 40684.0 | 25.185866 | 2.470259 |
7 | 192400 | 쿠쿠홀딩스 | 179204.666667 | 177500.0 | NaN | NaN | NaN | NaN | NaN |
8 | 199800 | 툴젠 | -2514.333333 | 115400.0 | NaN | NaN | NaN | NaN | NaN |
9 | 204210 | 모두투어리츠 | 3093.333333 | 3475.0 | 모두투어리츠 | 85.166667 | 5335.0 | 40.802348 | 0.651359 |
10 | 136480 | NaN | NaN | NaN | 하림 | 274.166667 | 3551.0 | 11.489362 | 0.887074 |
11 | 138040 | NaN | NaN | NaN | 메리츠금융지주 | 2122.333333 | 14894.0 | 6.313806 | 0.899691 |
12 | 161390 | NaN | NaN | NaN | 한국타이어 | 5648.500000 | 51341.0 | 7.453306 | 0.820007 |
13 | 181710 | NaN | NaN | NaN | NHN엔터테인먼트 | 2110.166667 | 78434.0 | 30.755864 | 0.827447 |
14 | 207940 | NaN | NaN | NaN | 삼성바이오로직스 | 4644.166667 | 60099.0 | 89.790059 | 6.938551 |
# 왼쪽 데이터프레임(df1)에서는 stock_name, 오른쪽 데이터프레임(df2)에서는 name을 조인조건으로 하되
# left join
pd.merge(df1, df2, left_on='stock_name', right_on='name', how='left')
id_x | stock_name | value | price | id_y | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 128940 | 한미약품 | 59385.666667 | 421000 | NaN | NaN | NaN | NaN | NaN | NaN |
1 | 130960 | CJ E&M | 58540.666667 | 98900 | 130960.0 | CJ E&M | 6301.333333 | 54068.0 | 15.695091 | 1.829178 |
2 | 138250 | 엔에스쇼핑 | 14558.666667 | 13200 | NaN | NaN | NaN | NaN | NaN | NaN |
3 | 139480 | 이마트 | 239230.833333 | 254500 | 139480.0 | 이마트 | 18268.166667 | 295780.0 | 13.931338 | 0.860437 |
4 | 142280 | 녹십자엠에스 | 468.833333 | 10200 | NaN | NaN | NaN | NaN | NaN | NaN |
5 | 145990 | 삼양사 | 82750.000000 | 82000 | 145990.0 | 삼양사 | 5741.000000 | 108090.0 | 14.283226 | 0.758627 |
6 | 185750 | 종근당 | 40293.666667 | 100500 | 185750.0 | 종근당 | 3990.333333 | 40684.0 | 25.185866 | 2.470259 |
7 | 192400 | 쿠쿠홀딩스 | 179204.666667 | 177500 | NaN | NaN | NaN | NaN | NaN | NaN |
8 | 199800 | 툴젠 | -2514.333333 | 115400 | NaN | NaN | NaN | NaN | NaN | NaN |
9 | 204210 | 모두투어리츠 | 3093.333333 | 3475 | 204210.0 | 모두투어리츠 | 85.166667 | 5335.0 | 40.802348 | 0.651359 |
# 왼쪽 데이터프레임(df1)에서는 stock_name, 오른쪽 데이터프레임(df2)에서는 name을 조인조건으로 하되
# right join
pd.merge(df1, df2, left_on='stock_name', right_on='name', how='right')
id_x | stock_name | value | price | id_y | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 130960.0 | CJ E&M | 58540.666667 | 98900.0 | 130960 | CJ E&M | 6301.333333 | 54068 | 15.695091 | 1.829178 |
1 | NaN | NaN | NaN | NaN | 136480 | 하림 | 274.166667 | 3551 | 11.489362 | 0.887074 |
2 | NaN | NaN | NaN | NaN | 138040 | 메리츠금융지주 | 2122.333333 | 14894 | 6.313806 | 0.899691 |
3 | 139480.0 | 이마트 | 239230.833333 | 254500.0 | 139480 | 이마트 | 18268.166667 | 295780 | 13.931338 | 0.860437 |
4 | 145990.0 | 삼양사 | 82750.000000 | 82000.0 | 145990 | 삼양사 | 5741.000000 | 108090 | 14.283226 | 0.758627 |
5 | NaN | NaN | NaN | NaN | 161390 | 한국타이어 | 5648.500000 | 51341 | 7.453306 | 0.820007 |
6 | NaN | NaN | NaN | NaN | 181710 | NHN엔터테인먼트 | 2110.166667 | 78434 | 30.755864 | 0.827447 |
7 | 185750.0 | 종근당 | 40293.666667 | 100500.0 | 185750 | 종근당 | 3990.333333 | 40684 | 25.185866 | 2.470259 |
8 | 204210.0 | 모두투어리츠 | 3093.333333 | 3475.0 | 204210 | 모두투어리츠 | 85.166667 | 5335 | 40.802348 | 0.651359 |
9 | NaN | NaN | NaN | NaN | 207940 | 삼성바이오로직스 | 4644.166667 | 60099 | 89.790059 | 6.938551 |
- 색인 병합으로 데이터프레임 합치기
df1 = pd.read_excel('./examples/stock price.xlsx', index_col = 'id')
df2 = pd.read_excel('./examples/stock valuation.xlsx', index_col = 'id')
df1
stock_name | value | price | |
---|---|---|---|
id | |||
128940 | 한미약품 | 59385.666667 | 421000 |
130960 | CJ E&M | 58540.666667 | 98900 |
138250 | 엔에스쇼핑 | 14558.666667 | 13200 |
139480 | 이마트 | 239230.833333 | 254500 |
142280 | 녹십자엠에스 | 468.833333 | 10200 |
145990 | 삼양사 | 82750.000000 | 82000 |
185750 | 종근당 | 40293.666667 | 100500 |
192400 | 쿠쿠홀딩스 | 179204.666667 | 177500 |
199800 | 툴젠 | -2514.333333 | 115400 |
204210 | 모두투어리츠 | 3093.333333 | 3475 |
df2
name | eps | bps | per | pbr | |
---|---|---|---|---|---|
id | |||||
130960 | CJ E&M | 6301.333333 | 54068 | 15.695091 | 1.829178 |
136480 | 하림 | 274.166667 | 3551 | 11.489362 | 0.887074 |
138040 | 메리츠금융지주 | 2122.333333 | 14894 | 6.313806 | 0.899691 |
139480 | 이마트 | 18268.166667 | 295780 | 13.931338 | 0.860437 |
145990 | 삼양사 | 5741.000000 | 108090 | 14.283226 | 0.758627 |
161390 | 한국타이어 | 5648.500000 | 51341 | 7.453306 | 0.820007 |
181710 | NHN엔터테인먼트 | 2110.166667 | 78434 | 30.755864 | 0.827447 |
185750 | 종근당 | 3990.333333 | 40684 | 25.185866 | 2.470259 |
204210 | 모두투어리츠 | 85.166667 | 5335 | 40.802348 | 0.651359 |
207940 | 삼성바이오로직스 | 4644.166667 | 60099 | 89.790059 | 6.938551 |
# 데이터프레임 인덱스를 기준으로 병합 (왼쪽 데이터프레임(df1) 기준)
df1.join(df2) # how='left' 가 기본값
stock_name | value | price | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|
id | ||||||||
128940 | 한미약품 | 59385.666667 | 421000 | NaN | NaN | NaN | NaN | NaN |
130960 | CJ E&M | 58540.666667 | 98900 | CJ E&M | 6301.333333 | 54068.0 | 15.695091 | 1.829178 |
138250 | 엔에스쇼핑 | 14558.666667 | 13200 | NaN | NaN | NaN | NaN | NaN |
139480 | 이마트 | 239230.833333 | 254500 | 이마트 | 18268.166667 | 295780.0 | 13.931338 | 0.860437 |
142280 | 녹십자엠에스 | 468.833333 | 10200 | NaN | NaN | NaN | NaN | NaN |
145990 | 삼양사 | 82750.000000 | 82000 | 삼양사 | 5741.000000 | 108090.0 | 14.283226 | 0.758627 |
185750 | 종근당 | 40293.666667 | 100500 | 종근당 | 3990.333333 | 40684.0 | 25.185866 | 2.470259 |
192400 | 쿠쿠홀딩스 | 179204.666667 | 177500 | NaN | NaN | NaN | NaN | NaN |
199800 | 툴젠 | -2514.333333 | 115400 | NaN | NaN | NaN | NaN | NaN |
204210 | 모두투어리츠 | 3093.333333 | 3475 | 모두투어리츠 | 85.166667 | 5335.0 | 40.802348 | 0.651359 |
# 데이터프레임 인덱스를 기준으로 병합 (공통된 인덱스만)
df1.join(df2, how='inner')
stock_name | value | price | name | eps | bps | per | pbr | |
---|---|---|---|---|---|---|---|---|
id | ||||||||
130960 | CJ E&M | 58540.666667 | 98900 | CJ E&M | 6301.333333 | 54068 | 15.695091 | 1.829178 |
139480 | 이마트 | 239230.833333 | 254500 | 이마트 | 18268.166667 | 295780 | 13.931338 | 0.860437 |
145990 | 삼양사 | 82750.000000 | 82000 | 삼양사 | 5741.000000 | 108090 | 14.283226 | 0.758627 |
185750 | 종근당 | 40293.666667 | 100500 | 종근당 | 3990.333333 | 40684 | 25.185866 | 2.470259 |
204210 | 모두투어리츠 | 3093.333333 | 3475 | 모두투어리츠 | 85.166667 | 5335 | 40.802348 | 0.651359 |
9.3 그룹연산
(1) 그룹 객체 만들기
titanic = pd.read_csv('./datasets/titanic_train.csv')
titanic.head()
titanic['Pclass'].unique()
array([3, 1, 2])
titanic['Pclass'].value_counts()
3 491
1 216
2 184
Name: Pclass, dtype: int64
- 한 컬럼을 기준으로 그룹화
grouped = titanic.groupby('Pclass')
grouped
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f040107bfa0>
# grouped 객체를 순회
for group_key, group in grouped:
print('group key :', group_key)
print('length of group : ', len(group))
last_group = group.head(3)
last_group
group key : 1
length of group : 216
group key : 2
length of group : 184
group key : 3
length of group : 491
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.250 | NaN | S |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.925 | NaN | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.050 | NaN | S |
# 각 그룹들의 평균
grouped.mean()
PassengerId | Survived | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|
Pclass | ||||||
1 | 461.597222 | 0.629630 | 38.233441 | 0.416667 | 0.356481 | 84.154687 |
2 | 445.956522 | 0.472826 | 29.877630 | 0.402174 | 0.380435 | 20.662183 |
3 | 439.154786 | 0.242363 | 25.140620 | 0.615071 | 0.393075 | 13.675550 |
grouped.mean()['Survived'] # 그룹별 생존률
Pclass
1 0.629630
2 0.472826
3 0.242363
Name: Survived, dtype: float64
grouped.mean()['Age'] # 그룹별 나이 평균
Pclass
1 38.233441
2 29.877630
3 25.140620
Name: Age, dtype: float64
grouped.mean()['Fare'] # 그룹별 요금 평균균
Pclass
1 84.154687
2 20.662183
3 13.675550
Name: Fare, dtype: float64
# 한 그룹만 추출
first_group = grouped.get_group(1) # Pclass =1 인 그룹만 DF 으로 반환
first_group.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
6 | 7 | 0 | 1 | McCarthy, Mr. Timothy J | male | 54.0 | 0 | 0 | 17463 | 51.8625 | E46 | S |
- 두 컬럼을 기준으로 그룹화
grouped2 = titanic.groupby(['Pclass', 'Sex'])
grouped2
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f0401056400>
# grouped2 객체를 순회
for group_key, group in grouped2:
print('group key :', group_key)
print('length of group :', len(group))
group key : (1, 'female')
length of group : 94
group key : (1, 'male')
length of group : 122
group key : (2, 'female')
length of group : 76
group key : (2, 'male')
length of group : 108
group key : (3, 'female')
length of group : 144
group key : (3, 'male')
length of group : 347
# 각 그룹들의 평균
grouped2.mean()
PassengerId | Survived | Age | SibSp | Parch | Fare | ||
---|---|---|---|---|---|---|---|
Pclass | Sex | ||||||
1 | female | 469.212766 | 0.968085 | 34.611765 | 0.553191 | 0.457447 | 106.125798 |
male | 455.729508 | 0.368852 | 41.281386 | 0.311475 | 0.278689 | 67.226127 | |
2 | female | 443.105263 | 0.921053 | 28.722973 | 0.486842 | 0.605263 | 21.970121 |
male | 447.962963 | 0.157407 | 30.740707 | 0.342593 | 0.222222 | 19.741782 | |
3 | female | 399.729167 | 0.500000 | 21.750000 | 0.895833 | 0.798611 | 16.118810 |
male | 455.515850 | 0.135447 | 26.507589 | 0.498559 | 0.224784 | 12.661633 |
grouped2.mean()['Survived'] # 각 그룹의 생존률률
Pclass Sex
1 female 0.968085
male 0.368852
2 female 0.921053
male 0.157407
3 female 0.500000
male 0.135447
Name: Survived, dtype: float64
grouped2.mean()['Age']
Pclass Sex
1 female 34.611765
male 41.281386
2 female 28.722973
male 30.740707
3 female 21.750000
male 26.507589
Name: Age, dtype: float64
grouped2.mean()['Fare']
Pclass Sex
1 female 106.125798
male 67.226127
2 female 21.970121
male 19.741782
3 female 16.118810
male 12.661633
Name: Fare, dtype: float64
first_female_group = grouped2.get_group((1, 'female'))
first_female_group.head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
11 | 12 | 1 | 1 | Bonnell, Miss. Elizabeth | female | 58.0 | 0 | 0 | 113783 | 26.5500 | C103 | S |
31 | 32 | 1 | 1 | Spencer, Mrs. William Augustus (Marie Eugenie) | female | NaN | 1 | 0 | PC 17569 | 146.5208 | B78 | C |
52 | 53 | 1 | 1 | Harper, Mrs. Henry Sleeper (Myna Haxtun) | female | 49.0 | 1 | 0 | PC 17572 | 76.7292 | D33 | C |
(2) 그룹 연산 메소드
grouped = titanic.groupby('Pclass')
grouped.mean() # 그룹별 평균
PassengerId | Survived | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|
Pclass | ||||||
1 | 461.597222 | 0.629630 | 38.233441 | 0.416667 | 0.356481 | 84.154687 |
2 | 445.956522 | 0.472826 | 29.877630 | 0.402174 | 0.380435 | 20.662183 |
3 | 439.154786 | 0.242363 | 25.140620 | 0.615071 | 0.393075 | 13.675550 |
grouped.agg('mean') # agg(적용하고자 하는 함수), mean은 이미 제공되는 함수라서 문자열로 배치
PassengerId | Survived | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|
Pclass | ||||||
1 | 461.597222 | 0.629630 | 38.233441 | 0.416667 | 0.356481 | 84.154687 |
2 | 445.956522 | 0.472826 | 29.877630 | 0.402174 | 0.380435 | 20.662183 |
3 | 439.154786 | 0.242363 | 25.140620 | 0.615071 | 0.393075 | 13.675550 |
def min_max(x):
return x.max() - x.min()
grouped.agg(min_max) # agg(적용하고자 하는 함수), min_max를 적용함으로 각 열의 최댓값과 최솟값의 차이를 조회해 볼 수 있음음
# grouped[['PassengerId', 'Survived', 'Age', 'SibSp', 'Parch', 'Fare']].agg(min_max)
/usr/local/lib/python3.8/dist-packages/pandas/core/groupby/generic.py:303: FutureWarning: Dropping invalid columns in SeriesGroupBy.agg is deprecated. In a future version, a TypeError will be raised. Before calling .agg, select only columns which should be valid for the aggregating function.
results[key] = self.aggregate(func)
PassengerId | Survived | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|
Pclass | ||||||
1 | 888 | 1 | 79.08 | 3 | 4 | 512.3292 |
2 | 877 | 1 | 69.33 | 3 | 3 | 73.5000 |
3 | 890 | 1 | 73.58 | 8 | 6 | 69.5500 |
grouped.agg(['mean', 'min', 'max']) # 여러 함수를 매핑할 수도 있음
PassengerId | Survived | Age | SibSp | Parch | Fare | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
mean | min | max | mean | min | max | mean | min | max | mean | min | max | mean | min | max | mean | min | max | |
Pclass | ||||||||||||||||||
1 | 461.597222 | 2 | 890 | 0.629630 | 0 | 1 | 38.233441 | 0.92 | 80.0 | 0.416667 | 0 | 3 | 0.356481 | 0 | 4 | 84.154687 | 0.0 | 512.3292 |
2 | 445.956522 | 10 | 887 | 0.472826 | 0 | 1 | 29.877630 | 0.67 | 70.0 | 0.402174 | 0 | 3 | 0.380435 | 0 | 3 | 20.662183 | 0.0 | 73.5000 |
3 | 439.154786 | 1 | 891 | 0.242363 | 0 | 1 | 25.140620 | 0.42 | 74.0 | 0.615071 | 0 | 8 | 0.393075 | 0 | 6 | 13.675550 | 0.0 | 69.5500 |
grouped.agg({'Survived' :'mean', 'Age':['min', 'max']})
Survived | Age | ||
---|---|---|---|
mean | min | max | |
Pclass | |||
1 | 0.629630 | 0.92 | 80.0 |
2 | 0.472826 | 0.67 | 70.0 |
3 | 0.242363 | 0.42 | 74.0 |
# 데이터 변환
grouped['Fare'].transform(lambda x: x*1.2) # 파운드를 달러로 변환
0 8.70000
1 85.53996
2 9.51000
3 63.72000
4 9.66000
...
886 15.60000
887 36.00000
888 28.14000
889 36.00000
890 9.30000
Name: Fare, Length: 891, dtype: float64
# 데이터 필터링
grouped.filter(lambda x : len(x) >= 200) # 그룹의 갯수가 200개 이상인 그룹만 가져옴
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
885 | 886 | 0 | 3 | Rice, Mrs. William (Margaret Norton) | female | 39.0 | 0 | 5 | 382652 | 29.1250 | NaN | Q |
887 | 888 | 1 | 1 | Graham, Miss. Margaret Edith | female | 19.0 | 0 | 0 | 112053 | 30.0000 | B42 | S |
888 | 889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | S |
889 | 890 | 1 | 1 | Behr, Mr. Karl Howell | male | 26.0 | 0 | 0 | 111369 | 30.0000 | C148 | C |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
707 rows × 12 columns
grouped.filter(lambda x: x.Age.mean() < 30) # Age열의 그룹 평균이 30보다 작은 그룹만을 선택(2, 3 Class)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
5 | 6 | 0 | 3 | Moran, Mr. James | male | NaN | 0 | 0 | 330877 | 8.4583 | NaN | Q |
7 | 8 | 0 | 3 | Palsson, Master. Gosta Leonard | male | 2.0 | 3 | 1 | 349909 | 21.0750 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
884 | 885 | 0 | 3 | Sutehall, Mr. Henry Jr | male | 25.0 | 0 | 0 | SOTON/OQ 392076 | 7.0500 | NaN | S |
885 | 886 | 0 | 3 | Rice, Mrs. William (Margaret Norton) | female | 39.0 | 0 | 5 | 382652 | 29.1250 | NaN | Q |
886 | 887 | 0 | 2 | Montvila, Rev. Juozas | male | 27.0 | 0 | 0 | 211536 | 13.0000 | NaN | S |
888 | 889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | S |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
675 rows × 12 columns
# 함수 매핑
grouped.apply(lambda x: x.describe())
# grouped.filter(lambda x: x.Age.mean() < 30) # filter : 조건에 해당하는 그룹까지 가져오기
grouped.apply(lambda x: x.Age.mean() < 30) # apply : 해당식의 판별 결과 가져오기
Pclass
1 False
2 True
3 True
dtype: bool
t = titanic.groupby(['Pclass', 'Survived']).size()
t
Pclass Survived
1 0 80
1 136
2 0 97
1 87
3 0 372
1 119
dtype: int64
t.index
MultiIndex([(1, 0),
(1, 1),
(2, 0),
(2, 1),
(3, 0),
(3, 1)],
names=['Pclass', 'Survived'])
t.unstack()
Survived | 0 | 1 |
---|---|---|
Pclass | ||
1 | 80 | 136 |
2 | 97 | 87 |
3 | 372 | 119 |
t.unstack().stack()
Pclass Survived
1 0 80
1 136
2 0 97
1 87
3 0 372
1 119
dtype: int64
9.4 Pivot, Melt
from IPython.display import Image
Image('./images/reshaping_pivot.png', width=600)
# Pandas example
df = pd.DataFrame({'foo': ['one', 'one', 'one', 'two', 'two',
'two'],
'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
'baz': [1, 2, 3, 4, 5, 6],
'zoo': ['x', 'y', 'z', 'q', 'w', 't']})
df
foo | bar | baz | zoo | |
---|---|---|---|---|
0 | one | A | 1 | x |
1 | one | B | 2 | y |
2 | one | C | 3 | z |
3 | two | A | 4 | q |
4 | two | B | 5 | w |
5 | two | C | 6 | t |
df.pivot(index='foo', columns='bar', values='baz')
bar | A | B | C |
---|---|---|---|
foo | |||
one | 1 | 2 | 3 |
two | 4 | 5 | 6 |
Image('./images/reshaping_melt.png', width=600)
cheese = pd.DataFrame(
{
"first": ["John", "Mary"],
"last": ["Doe", "Bo"],
"height": [5.5, 6.0],
"weight": [130, 150],
}
)
cheese
first | last | height | weight | |
---|---|---|---|---|
0 | John | Doe | 5.5 | 130 |
1 | Mary | Bo | 6.0 | 150 |
cheese.melt(id_vars=['first', 'last'])
first | last | variable | value | |
---|---|---|---|---|
0 | John | Doe | height | 5.5 |
1 | Mary | Bo | height | 6.0 |
2 | John | Doe | weight | 130.0 |
3 | Mary | Bo | weight | 150.0 |
추가 예제
Image('./images/long_wide_format.png', width=600)
df = pd.DataFrame(
{
'Item': ['Cereals', 'Dairy', 'Frozen', 'Meat'],
'Price': [100, 50, 200, 250],
'Hour_1': [5, 5, 3, 8],
'Hour_2': [8, 8, 2, 1],
'Hour_3': [7, 7, 8, 2]
}
)
df
Item | Price | Hour_1 | Hour_2 | Hour_3 | |
---|---|---|---|---|---|
0 | Cereals | 100 | 5 | 8 | 7 |
1 | Dairy | 50 | 5 | 8 | 7 |
2 | Frozen | 200 | 3 | 2 | 8 |
3 | Meat | 250 | 8 | 1 | 2 |
from wide format to long format
melted_df = pd.melt(df, id_vars=['Item'], value_vars=('Hour_1', 'Hour_2', 'Hour_3'),
var_name='Hour', value_name='Sales')
melted_df
Item | Hour | Sales | |
---|---|---|---|
0 | Cereals | Hour_1 | 5 |
1 | Dairy | Hour_1 | 5 |
2 | Frozen | Hour_1 | 3 |
3 | Meat | Hour_1 | 8 |
4 | Cereals | Hour_2 | 8 |
5 | Dairy | Hour_2 | 8 |
6 | Frozen | Hour_2 | 2 |
7 | Meat | Hour_2 | 1 |
8 | Cereals | Hour_3 | 7 |
9 | Dairy | Hour_3 | 7 |
10 | Frozen | Hour_3 | 8 |
11 | Meat | Hour_3 | 2 |
melted_df.groupby('Item').sum()
Sales | |
---|---|
Item | |
Cereals | 20 |
Dairy | 20 |
Frozen | 13 |
Meat | 11 |
melted_df.groupby('Hour').sum()
Sales | |
---|---|
Hour | |
Hour_1 | 21 |
Hour_2 | 19 |
Hour_3 | 24 |
# price 포함
melted_df = pd.melt(df, id_vars=['Item', 'Price'],
value_vars = ('Hour_1', 'Hour_2', 'Hour_3'),
var_name = 'Hour',
value_name = 'Sales')
melted_df
Item | Price | Hour | Sales | |
---|---|---|---|---|
0 | Cereals | 100 | Hour_1 | 5 |
1 | Dairy | 50 | Hour_1 | 5 |
2 | Frozen | 200 | Hour_1 | 3 |
3 | Meat | 250 | Hour_1 | 8 |
4 | Cereals | 100 | Hour_2 | 8 |
5 | Dairy | 50 | Hour_2 | 8 |
6 | Frozen | 200 | Hour_2 | 2 |
7 | Meat | 250 | Hour_2 | 1 |
8 | Cereals | 100 | Hour_3 | 7 |
9 | Dairy | 50 | Hour_3 | 7 |
10 | Frozen | 200 | Hour_3 | 8 |
11 | Meat | 250 | Hour_3 | 2 |
melted_df['Sale_amt'] = melted_df['Price'] * melted_df['Sales']
melted_df
Item | Price | Hour | Sales | Sale_amt | |
---|---|---|---|---|---|
0 | Cereals | 100 | Hour_1 | 5 | 500 |
1 | Dairy | 50 | Hour_1 | 5 | 250 |
2 | Frozen | 200 | Hour_1 | 3 | 600 |
3 | Meat | 250 | Hour_1 | 8 | 2000 |
4 | Cereals | 100 | Hour_2 | 8 | 800 |
5 | Dairy | 50 | Hour_2 | 8 | 400 |
6 | Frozen | 200 | Hour_2 | 2 | 400 |
7 | Meat | 250 | Hour_2 | 1 | 250 |
8 | Cereals | 100 | Hour_3 | 7 | 700 |
9 | Dairy | 50 | Hour_3 | 7 | 350 |
10 | Frozen | 200 | Hour_3 | 8 | 1600 |
11 | Meat | 250 | Hour_3 | 2 | 500 |
melted_df.groupby('Hour').sum()['Sale_amt'] # 시간대별 매출량 집계계
Hour
Hour_1 3350
Hour_2 1850
Hour_3 3150
Name: Sale_amt, dtype: int64
melted_df.groupby('Item').sum()['Sale_amt']
Item
Cereals 2000
Dairy 1000
Frozen 2600
Meat 2750
Name: Sale_amt, dtype: int64
from long format to wide format
pivoted_df = melted_df.pivot(index=['Item', 'Price'], columns='Hour', values='Sales')
pivoted_df
Hour | Hour_1 | Hour_2 | Hour_3 | |
---|---|---|---|---|
Item | Price | |||
Cereals | 100 | 5 | 8 | 7 |
Dairy | 50 | 5 | 8 | 7 |
Frozen | 200 | 3 | 2 | 8 |
Meat | 250 | 8 | 1 | 2 |
Workshop
cpi = pd.read_excel('./datasets/CPI2.xlsx')
cpi
Year | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2001 | 175.100 | 175.800 | 176.200 | 176.900 | 177.700 | 178.000 | 177.500 | 177.500 | 178.300 | 177.700 | 177.400 | 176.700 |
1 | 2002 | 177.100 | 177.800 | 178.800 | 179.800 | 179.800 | 179.900 | 180.100 | 180.700 | 181.000 | 181.300 | 181.300 | 180.900 |
2 | 2003 | 181.700 | 183.100 | 184.200 | 183.800 | 183.500 | 183.700 | 183.900 | 184.600 | 185.200 | 185.000 | 184.500 | 184.300 |
3 | 2004 | 185.200 | 186.200 | 187.400 | 188.000 | 189.100 | 189.700 | 189.400 | 189.500 | 189.900 | 190.900 | 191.000 | 190.300 |
4 | 2005 | 190.700 | 191.800 | 193.300 | 194.600 | 194.400 | 194.500 | 195.400 | 196.400 | 198.800 | 199.200 | 197.600 | 196.800 |
5 | 2006 | 198.300 | 198.700 | 199.800 | 201.500 | 202.500 | 202.900 | 203.500 | 203.900 | 202.900 | 201.800 | 201.500 | 201.800 |
6 | 2007 | 202.416 | 203.499 | 205.352 | 206.686 | 207.949 | 208.352 | 208.299 | 207.917 | 208.490 | 208.936 | 210.177 | 210.036 |
7 | 2008 | 211.080 | 211.693 | 213.528 | 214.823 | 216.632 | 218.815 | 219.964 | 219.086 | 218.783 | 216.573 | 212.425 | 210.228 |
8 | 2009 | 211.143 | 212.193 | 212.709 | 213.240 | 213.856 | 215.693 | 215.351 | 215.834 | 215.969 | 216.177 | 216.330 | 215.949 |
9 | 2010 | 216.687 | 216.741 | 217.631 | 218.009 | 218.178 | 217.965 | 218.011 | 218.312 | 218.439 | 218.711 | 218.803 | 219.179 |
10 | 2011 | 220.223 | 221.309 | 223.467 | 224.906 | 225.964 | 225.722 | 225.922 | 226.545 | 226.889 | 226.421 | 226.230 | 225.672 |
11 | 2012 | 226.665 | 227.663 | 229.392 | 230.085 | 229.815 | 229.478 | 229.104 | 230.379 | 231.407 | 231.317 | 230.221 | 229.601 |
12 | 2013 | 230.280 | 232.166 | 232.773 | 232.531 | 232.945 | 233.504 | 233.596 | 233.877 | 234.149 | 233.546 | 233.069 | 233.049 |
13 | 2014 | 233.916 | 234.781 | 236.293 | 237.072 | 237.900 | 238.343 | 238.250 | 237.852 | 238.031 | 237.433 | 236.151 | 234.812 |
14 | 2015 | 233.707 | 234.722 | 236.119 | 236.599 | 237.805 | 238.638 | 238.654 | 238.316 | 237.945 | 237.838 | 237.336 | 236.525 |
15 | 2016 | 236.916 | 237.111 | 238.132 | 239.261 | 240.229 | 241.018 | 240.628 | 240.849 | 241.428 | 241.729 | 241.353 | 241.432 |
16 | 2017 | 242.839 | 243.603 | 243.801 | 244.524 | 244.733 | 244.955 | 244.786 | 245.519 | 246.819 | 246.663 | 246.669 | 246.524 |
17 | 2018 | 247.867 | 248.991 | 249.554 | 250.546 | 251.588 | 251.989 | 252.006 | 252.146 | 252.439 | 252.885 | 252.038 | 251.233 |
18 | 2019 | 251.712 | 252.776 | 254.202 | 255.548 | 256.092 | 256.143 | 256.571 | 256.558 | 256.759 | 257.346 | 257.208 | 256.974 |
19 | 2020 | 257.971 | 258.678 | 258.115 | 256.389 | 256.394 | 257.797 | 259.101 | 259.918 | 260.280 | 260.388 | 260.229 | 260.474 |
20 | 2021 | 261.582 | 263.014 | 264.877 | 267.054 | 269.195 | 271.696 | 273.003 | 273.567 | 274.310 | 276.589 | 277.948 | 278.802 |
21 | 2022 | 281.148 | 283.716 | 287.504 | 289.109 | 292.296 | 296.311 | 296.276 | 296.171 | 296.808 | 298.012 | 297.711 | 296.797 |
22 | 2023 | 299.170 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
- wide to long format
melted_cpi = cpi.melt(id_vars=['Year'], var_name='Month', value_name='cpi')
melted_cpi
Year | Month | cpi | |
---|---|---|---|
0 | 2001 | Jan | 175.100 |
1 | 2002 | Jan | 177.100 |
2 | 2003 | Jan | 181.700 |
3 | 2004 | Jan | 185.200 |
4 | 2005 | Jan | 190.700 |
... | ... | ... | ... |
271 | 2019 | Dec | 256.974 |
272 | 2020 | Dec | 260.474 |
273 | 2021 | Dec | 278.802 |
274 | 2022 | Dec | 296.797 |
275 | 2023 | Dec | NaN |
276 rows × 3 columns
melted_cpi.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 276 entries, 0 to 275
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Year 276 non-null int64
1 Month 276 non-null object
2 cpi 265 non-null float64
dtypes: float64(1), int64(1), object(1)
memory usage: 6.6+ KB
# 참고
x = pd.to_datetime(melted_cpi['Month'], format='%b')
x
0 1900-01-01
1 1900-01-01
2 1900-01-01
3 1900-01-01
4 1900-01-01
...
271 1900-12-01
272 1900-12-01
273 1900-12-01
274 1900-12-01
275 1900-12-01
Name: Month, Length: 276, dtype: datetime64[ns]
melted_cpi['Month'] = melted_cpi['Month'].map(lambda x: pd.to_datetime(x, format='%b')).dt.month
melted_cpi
Year | Month | cpi | |
---|---|---|---|
0 | 2001 | 1 | 175.100 |
1 | 2002 | 1 | 177.100 |
2 | 2003 | 1 | 181.700 |
3 | 2004 | 1 | 185.200 |
4 | 2005 | 1 | 190.700 |
... | ... | ... | ... |
271 | 2019 | 12 | 256.974 |
272 | 2020 | 12 | 260.474 |
273 | 2021 | 12 | 278.802 |
274 | 2022 | 12 | 296.797 |
275 | 2023 | 12 | NaN |
276 rows × 3 columns
- 월별 cpi 평균 구하기
melted_cpi.groupby('Month').mean()['cpi']
Month
1 224.931391
2 222.548000
3 223.779500
4 224.590091
5 225.389591
6 226.141773
7 226.332818
8 226.611182
9 227.047500
10 227.112000
11 226.690818
12 226.276682
Name: cpi, dtype: float64
- 연도별 cpi 평균 구하기
melted_cpi.groupby('Year').mean()['cpi']
Year
2001 177.066667
2002 179.875000
2003 183.958333
2004 188.883333
2005 195.291667
2006 201.591667
2007 207.342417
2008 215.302500
2009 214.537000
2010 218.055500
2011 224.939167
2012 229.593917
2013 232.957083
2014 236.736167
2015 237.017000
2016 240.007167
2017 245.119583
2018 251.106833
2019 255.657417
2020 258.811167
2021 270.969750
2022 292.654917
2023 299.170000
Name: cpi, dtype: float64
- long to wide format
pivoted_cpi = melted_cpi.pivot(index='Year', columns='Month', values='cpi')
pivoted_cpi
Month | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Year | ||||||||||||
2001 | 175.100 | 175.800 | 176.200 | 176.900 | 177.700 | 178.000 | 177.500 | 177.500 | 178.300 | 177.700 | 177.400 | 176.700 |
2002 | 177.100 | 177.800 | 178.800 | 179.800 | 179.800 | 179.900 | 180.100 | 180.700 | 181.000 | 181.300 | 181.300 | 180.900 |
2003 | 181.700 | 183.100 | 184.200 | 183.800 | 183.500 | 183.700 | 183.900 | 184.600 | 185.200 | 185.000 | 184.500 | 184.300 |
2004 | 185.200 | 186.200 | 187.400 | 188.000 | 189.100 | 189.700 | 189.400 | 189.500 | 189.900 | 190.900 | 191.000 | 190.300 |
2005 | 190.700 | 191.800 | 193.300 | 194.600 | 194.400 | 194.500 | 195.400 | 196.400 | 198.800 | 199.200 | 197.600 | 196.800 |
2006 | 198.300 | 198.700 | 199.800 | 201.500 | 202.500 | 202.900 | 203.500 | 203.900 | 202.900 | 201.800 | 201.500 | 201.800 |
2007 | 202.416 | 203.499 | 205.352 | 206.686 | 207.949 | 208.352 | 208.299 | 207.917 | 208.490 | 208.936 | 210.177 | 210.036 |
2008 | 211.080 | 211.693 | 213.528 | 214.823 | 216.632 | 218.815 | 219.964 | 219.086 | 218.783 | 216.573 | 212.425 | 210.228 |
2009 | 211.143 | 212.193 | 212.709 | 213.240 | 213.856 | 215.693 | 215.351 | 215.834 | 215.969 | 216.177 | 216.330 | 215.949 |
2010 | 216.687 | 216.741 | 217.631 | 218.009 | 218.178 | 217.965 | 218.011 | 218.312 | 218.439 | 218.711 | 218.803 | 219.179 |
2011 | 220.223 | 221.309 | 223.467 | 224.906 | 225.964 | 225.722 | 225.922 | 226.545 | 226.889 | 226.421 | 226.230 | 225.672 |
2012 | 226.665 | 227.663 | 229.392 | 230.085 | 229.815 | 229.478 | 229.104 | 230.379 | 231.407 | 231.317 | 230.221 | 229.601 |
2013 | 230.280 | 232.166 | 232.773 | 232.531 | 232.945 | 233.504 | 233.596 | 233.877 | 234.149 | 233.546 | 233.069 | 233.049 |
2014 | 233.916 | 234.781 | 236.293 | 237.072 | 237.900 | 238.343 | 238.250 | 237.852 | 238.031 | 237.433 | 236.151 | 234.812 |
2015 | 233.707 | 234.722 | 236.119 | 236.599 | 237.805 | 238.638 | 238.654 | 238.316 | 237.945 | 237.838 | 237.336 | 236.525 |
2016 | 236.916 | 237.111 | 238.132 | 239.261 | 240.229 | 241.018 | 240.628 | 240.849 | 241.428 | 241.729 | 241.353 | 241.432 |
2017 | 242.839 | 243.603 | 243.801 | 244.524 | 244.733 | 244.955 | 244.786 | 245.519 | 246.819 | 246.663 | 246.669 | 246.524 |
2018 | 247.867 | 248.991 | 249.554 | 250.546 | 251.588 | 251.989 | 252.006 | 252.146 | 252.439 | 252.885 | 252.038 | 251.233 |
2019 | 251.712 | 252.776 | 254.202 | 255.548 | 256.092 | 256.143 | 256.571 | 256.558 | 256.759 | 257.346 | 257.208 | 256.974 |
2020 | 257.971 | 258.678 | 258.115 | 256.389 | 256.394 | 257.797 | 259.101 | 259.918 | 260.280 | 260.388 | 260.229 | 260.474 |
2021 | 261.582 | 263.014 | 264.877 | 267.054 | 269.195 | 271.696 | 273.003 | 273.567 | 274.310 | 276.589 | 277.948 | 278.802 |
2022 | 281.148 | 283.716 | 287.504 | 289.109 | 292.296 | 296.311 | 296.276 | 296.171 | 296.808 | 298.012 | 297.711 | 296.797 |
2023 | 299.170 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
pivoted_cpi.columns
Int64Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype='int64', name='Month')
댓글남기기