Boolean Selection
Boolean Series
- 직접 인덱싱을 하는게 아니라, 조건식으로 해당되는 컬럼만 추출 (>, <, ==)
tmp_series = pd.Series({"a":1, "b":2})
tmp_series > 2
# a False
# b False
# dtype: bool
DataFrame 내에서 Boolean Series 만들기
a = df['순이익률(%)'] > df['영업이익률(%)']
# 동일한 index(row)에 대해 비교
a.head()
# 0 False
# 1 False
# 2 False
# 3 False
# 4 False
# dtype: bool
Boolean series로 indexing 하기
df[a] // a : 위에서 선언한 boolean series
df.shape
# (681, 15)
df[a].shape // a가 True인 것만 가져왔기에, 사이즈가 변경됨
# (142, 15)
// df.loc[a].shape : df.loc[a] == df.loc[[9, 10, 13 ...]] true인 rows
Multiple boolean series
con1 = df["순이익률"] > df["영업이익률"]
con2 = df["PBR"] < 1
final_con = (con1 & con2) # Python 'and', 'or' 대신에 &, | 사용
일부 종목의 데이터만 가져오는 방법
1) multiple boolean series 이용
cond1 = df['종목명'] == "삼성전자"
cond2 = df['종목명'] == "현대건설"
cond3 = df['종목명'] == "삼성물산"
final_con = cond1 | cond2 | cond3
df[final_con]
2) index화 해서 loc으로 row-wise indexing을 이용해서 가져오는 방법
tmp_df = df.set_index('종목명')
tmp_df.head()
tmp_df.loc[['삼성전자', '현대건설', "삼성물산"]]
3) .isin() 함수 이용
name_list = ["삼성전자", "현대건설", "삼성물산"]
cond = df['종목명'].isin(name_list)
df[cond]
# df[df['종목명'].isin(name_list)].head(2)
# df.loc[df['종목명'].isin(name_list)].head(2)
# df.loc[df['종목명'].isin(name_list), ['종목명', 'ROA(%)', 'ROE(%)']].head(2)
.all()
- True : 해당 시리즈가 전부 True
- False : True가 아닌 것이 1개 이상 있다
(df["순이익률"] > 0).all()
.any()
- True : True인것이 1개 이상 있다.
- False : 해당 시리즈의 모든 값이 False
(df["순이익률"] > 0).any()
example : 가장 큰 5개 섹터에 해당되는 종목 추출
a = pd.read_csv("my_data/symbol_sector.csv", index_col=0)
a['Sector'].value_counts().nlargest(5)
# 기타 금융업 110
# 자동차 신품 부품 제조업 46
# 의약품 제조업 44
# 전자부품 제조업 38
# 1차 철강 제조업 38
# Name: Sector, dtype: int64
top_5_sector_list = a['Sector'].value_counts().nlargest(5).index
# Index(['기타 금융업', '자동차 신품 부품 제조업', '의약품 제조업', '전자부품 제조업', '1차 철강 제조업'], dtype='object')
a[a['Sector'].isin(top_5_sector_list)]
연산 Arithmetic
- DataFrame는 기준이 columns
- Series는 기준이 index
- 별도의 명시가 없다면 Series의 index가 DataFrame의 columns에 맞춰짐
axis
연산은 기본적으로 "axis를 변형(줄이거나 늘리는)하는 방식"
몇번째 axis를 없앨 것인가로 이해하면 편하다 (axis = 0 ...)
a = np.array([1,2,3])
b = np.array([1,2,3])
a+b
# array([2, 4, 6])
np.sum([a,b], axis=0)
# array([2,4,6])
np.sum([a,b], axis=1)
# array([6,6])
# Before : 2차원 이상 axis가 늘어날 때는 이해가 어려움
# 0 1 2
# 0 [1, 2, 2],
# 1 [1, 2, 2]
#
# After : n차원 axis도 이해 可
# axis=0 ---> 0 1
# axis=1 ---> 0 1 2 0 1 2
# [ [1, 2, 2], [1, 2, 2] ]
# axis=0 ---> 0 1
# axis=1 ---> 0 1 2 0 1 2
# axis=2 ---> 0 1 0, 1 0 0, 1 0, 1 0, 1
# [ [[1, 2], [2, 4], [2]], [[1, 2], [2, 2], [2, 2]] ]
* Note: shift+tab을 이용해서 주석 설명을 보는 것이 가장 정확함
* Example : 모멘텀(추세) 계산
b = pd.read_csv("my_data/multi_price.csv", index_col=[0])
b.loc["2018-08-09"]
momentum_series = b.loc["2018-08-09"] / b.loc["2017-08-09"] - 1
momentum_series.nlargest(3)
# DB 0.142
# DB금융투자 0.118
# CJ헬로 0.088
# dtype: float64
Handling nan
None == None
# True
np.nan == np.nan
# False
5 < np.nan
# False
5 >= np.nan
# False
5 == np.nan
# False
np.nan != 5
# True
nan이 있을 때의 Boolean Series
df1['b'] == df1['b']
# 0 False
# 1 True
# 2 False
# Name: b, dtype: bool
df1.ge(2) # Same with (df1 >= 2)
df1.le(2) # ge : greater or equal / le : less or equal
Nan Checking
For Series
df['순이익률(%)'].hasnans
# True
# Generate boolean series
df['순이익률(%)'].isnull()
# 0 False
# 1 False
# 2 False
# 3 False
# 4 False
# ...
# 676 False
# 677 False
# 678 False
# 679 False
# 680 False
# Name: 순이익률(%), Length: 681, dtype: bool
df['순이익률(%)'].isna().any()
# True
df['순이익률(%)'].isna().sum()
# 1
For DataFrame
a = df.isnull()
a.any(axis=0)
# 종목명 False
# 매출액(억원) True
# 영업이익률(%) True
# 순이익률(%) True
# 당기순이익(억원) True
# ROE(%) True
# ROA(%) True
# ROIC(%) True
# EPS(원) False
# BPS(원) False
# SPS(원) False
# PER(배) True
# PBR(배) False
# PSR(배) True
# price False
# price2 False
# dtype: bool
df.isnull().any().any()
# True
df.isnull().any().all()
# False
* 두 개의 DataFrame이 같은지 판단하라면, == 이 아니라 .equals()를 사용하자
df1['b'].equals(df1['b'])
# True
'Quant' 카테고리의 다른 글
Quant : Pandas - 데이터 합치기 (0) | 2022.04.05 |
---|---|
Quant : Pandas - Grouping (0) | 2022.03.27 |
Quant : Pandas - API (1) (0) | 2022.03.14 |
Quant : Pandas - Series & DataFrame (0) | 2022.03.12 |
Quant : 사전 계획 (0) | 2022.03.08 |