교차표(cross tabulation): crosstab
pandas.crosstab() 함수는 pd.pivot_table()로 생성되는 피봇테이블과 유사하지만 두 개이상의 변수들에 대한 교차표 작성에 집중합니다.
다음 자료는 코스피 일일자료를 호출한 것으로 Open, High, Low, Close, Volume, Change 특성으로 구성된 것입니다.
import numpy as np import pandas as pd import FinanceDataReader as fdr
st=pd.Timestamp(2023,8, 26) et=pd.Timestamp(2024, 8,8) nme=['Open', 'High','Low','Close', 'Change', 'Volume'] da=fdr.DataReader('KS11', st, et)[nme] da.head(2).round(3)
Open | High | Low | Close | Change | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
2023-08-28 | 2534.42 | 2543.41 | 2525.64 | 2543.41 | 0.010 | 483587568 |
2023-08-29 | 2550.76 | 2556.98 | 2545.27 | 2552.16 | 0.003 | 441365852 |
위 자료 da의 Change를 제외한 나머지 특성들(features)들을 1일 전값과의 변화율로 변환합니다.
da1=da.drop("Change", axis=1) da1=da1.pct_change() da1["chg"]=da.Change da1=da1.dropna() da1.head(3).round(3)
Open | High | Low | Close | Volume | chg | |
---|---|---|---|---|---|---|
Date | ||||||
2023-08-29 | 0.006 | 0.005 | 0.008 | 0.003 | -0.087 | 0.003 |
2023-08-30 | 0.010 | 0.008 | 0.006 | 0.004 | -0.175 | 0.003 |
2023-08-31 | -0.004 | -0.004 | -0.005 | -0.002 | 0.300 | -0.002 |
위 자료에서 Close, Volume을 제외한 다른 특성들을 목록화합니다.
da2=da1 border={} for i in ["Open", "High", "Low", "chg"]: da2[i],bor=pd.qcut(da1[i], q=5, labels=range(5), retbins=True) border[i]=bor da2.head(2)
Open | High | Low | Close | Volume | chg | |
---|---|---|---|---|---|---|
Date | ||||||
2023-08-29 | 3 | 3 | 4 | 0.00344 | -0.087309 | 3 |
2023-08-30 | 4 | 4 | 3 | 0.00355 | -0.175281 | 3 |
자료의 Open, High, Low, chg를 목록화한 각 계급(bin)들의 경계값은 다음과 같습니다.
border
{'Open': array([0. , 0.2, 1.4, 2.6, 3.8, 4. ]), 'High': array([0. , 0.2, 1.4, 2.6, 3.8, 4. ]), 'Low': array([0. , 0.2, 1.4, 2.6, 3.8, 4. ]), 'chg': array([-0.0877 , -0.00808, -0.00182, 0.00202, 0.0098 , 0.0566 ])}
위 자료 da2의 High와 Low의 각 계급에 대응되는 빈도수는 다음과 같습니다.
pd.crosstab(da2.High, da2.Low, margins=True)
Low | 0 | 1 | 2 | 3 | 4 | All |
---|---|---|---|---|---|---|
High | ||||||
0 | 32 | 11 | 1 | 1 | 2 | 47 |
1 | 13 | 17 | 13 | 3 | 0 | 46 |
2 | 0 | 15 | 19 | 10 | 2 | 46 |
3 | 2 | 3 | 9 | 25 | 7 | 46 |
4 | 0 | 0 | 4 | 7 | 36 | 47 |
All | 47 | 46 | 46 | 46 | 47 | 232 |
위 결과는 High, Low는 같은 구간에서 움직이는 경향이 높지만 두 특성이 다른 방향을 보이는 경향 역시 나타납니다. 위 결과를 정규화하기 위해 normalize=True를 지정합니다.
pd.crosstab(da2.High, da2.Low, margins=True, normalize=True).round(3)
Low | 0 | 1 | 2 | 3 | 4 | All |
---|---|---|---|---|---|---|
High | ||||||
0 | 0.138 | 0.047 | 0.004 | 0.004 | 0.009 | 0.203 |
1 | 0.056 | 0.073 | 0.056 | 0.013 | 0.000 | 0.198 |
2 | 0.000 | 0.065 | 0.082 | 0.043 | 0.009 | 0.198 |
3 | 0.009 | 0.013 | 0.039 | 0.108 | 0.030 | 0.198 |
4 | 0.000 | 0.000 | 0.017 | 0.030 | 0.155 | 0.203 |
All | 0.203 | 0.198 | 0.198 | 0.198 | 0.203 | 1.000 |
High와 chg의 교차표는 다음과 같습니다.
pd.crosstab(da2.High, da2.chg)
chg | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
High | |||||
0 | 24 | 14 | 6 | 2 | 1 |
1 | 16 | 14 | 11 | 4 | 1 |
2 | 5 | 8 | 23 | 8 | 2 |
3 | 2 | 8 | 4 | 23 | 9 |
4 | 0 | 2 | 2 | 10 | 33 |
위 결과의 각 셀에 대응하는 Close의 평균은 다음과 같습니다. pd.crosstab() 함수에서 values를 지정하며 aggfunc를 함께 지정해야 합니다.
pd.crosstab(da2.High, da2.chg, values=da2.Close, aggfunc="mean").round(4)
chg | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
High | |||||
0 | -0.0204 | -0.0057 | 0.0003 | 0.0047 | 0.0330 |
1 | -0.0111 | -0.0054 | 0.0002 | 0.0046 | 0.0103 |
2 | -0.0094 | -0.0055 | 0.0003 | 0.0041 | 0.0119 |
3 | -0.0113 | -0.0035 | 0.0002 | 0.0057 | 0.0141 |
4 | NaN | -0.0025 | 0.0015 | 0.0065 | 0.0161 |
댓글
댓글 쓰기