선수별로 SVM은 나중에 구해보고 원래대로 한국에서 경기수와 승률 상위 20%와 하위 20%의 스탯을 뽑아 승패를 학습하기
throw_df = pd.read_csv('률lus_win_lose_2.csv')
top20 = throw_df.sort_values(['승률','경기수'], ascending=False).reset_index(drop=True)[:20]
bottom20 = throw_df.sort_values(['승률','경기수'], ascending=False).reset_index(drop=True)[-20:]
display(top20)
display(bottom20)
- 단순히 승률로만 본다면 1경기 뛰고 이기면 100%여서 경기수도 같이 보았다.

- 상위 20명이여서 그런지 방출도 없다.
- 익숙한 이름들이 많다.

머신러닝
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
feature = throw_df.drop('승',axis=1)
label = throw_df['승']
X_train, X_test, y_train, y_test = train_test_split(feature,label, test_size = 0.2, random_state=20)
- 승을 기준으로 피처와 라벨을 나워서 학습과 테스트 테이터를 나눈다.
base_dtc = DecisionTreeClassifier(random_state=20, criterion='entropy')
base_dtc.fit(X_train, y_train)
predition = base_dtc.predict(X_test)

- 라벨링을 안해서 오류가 발생하였다. 선수이름과 팀, 승을 라벨링해서 다시 나누자.
NaN 값 0으로 대체
throw_df['year_born'] = throw_df['year_born'].fillna(0)
throw_df['방출연도'] = throw_df['방출연도'].fillna(0)
throw_df.info()
from sklearn.preprocessing import LabelEncoder
def label(df):
col = list(df)
encoder = LabelEncoder()
encoder.fit(col)
col_label = encoder.transform(col)
return col_label
pitcher_name_label = label(throw_df['pitcher_name'])
team_label = label(throw_df['team'])
year_born_label = label(throw_df['year_born'])
- info에서 object인 컬럼들만 라벨인코딩을 실시하였다.
throw_df = throw_df.assign(pitcher_name_label=pitcher_name_label,
team_label=team_label,
year_born_label=year_born_label)
throw_df_digit = throw_df.drop(['pitcher_name','team','year_born','year'],axis=1)
throw_df_digit.head()
- df에 컬럼으로 추가하고 기존에 있던 object컬럼을 제거하였다.
from sklearn.metrics import accuracy_score
print(f'예측 정확도 : {accuracy_score(y_test, predition)}')
>
예측 정확도 : 0.19047619047619047
- 다시 예측을 실시하였는데 거의 예측을 안하니만큼 정확도가 나왔다. 정규화나 표준화를 해야겠다.
- 외국인 스카우트에 있는 정보들을 선수마다 평균을 내서 적용하려고 했지만 한국에서 경기간 횟수가 여러번이면 적용하기 애매해서 우선 참고용으로 쓰기로 하였다.
- year_born은 찾아서 해당 연도에 나이를 컬럼으로 추가하고 방출연도는 방출된 해에 1로 없는해에는 0으로 바꿔서 전체 변수 중요도를 살펴봐야겠다.
- 다시 보니 2011~2018년도를 학습 데이터로 두고 2019년도를 검증 데이터로 쓰라고 준 것 같다. 그러면 뭔가 학습을 시켜야 하는데 낮게 나와서 의미가 있나 싶다.
- 그럼 승, 패를 두 가지의 선택지라고 두고 의사결정나무로 다시 한 번 머신러닝을 돌려보려고 한다. 방출되지 않은 선수들의 외국 기록을 평균내어서 알고리즘으로 만들고 라벨링을 줘서 그 값을 다시 한국기록데이터에 넣어서 머신러닝을 돌려보려고 한다.
- 계획을 하고 코드를 작성하는게 빠르고 이제 이 미니 프로젝트를 끝내기에 맞는 것 같다.
단계 |
내용 |
진행/완료 |
1 |
투수들의 한국 경기 승, 패 여부 |
완료 |
2 |
투수들의 외국 경기 기록 평균으로 변환하여 다시 저장 |
|
- 기존에 만들어 놓았던 데이터 중에서 구종의 개수를 추가하여 형성 |
진행 |
|
3 |
투수들의 외국 경기 평균 기록에 한국 승패를 추가 |
- |
4 |
1. 한국 기록 데이터 셋 |
|
2. 외국 기록 데이터 셋으로 각각 의사결정 나무 진행 |
|
|
3. 마지막으로 두개의 데이터를 하나로 합쳐서 의사결정나무 진행 |
- |
|
5 |
위의 결과를 보고 이제 2011~2018데이터를 학습 데이터로 두고 2019 데이터를 검증 데이터로 활용 |
- |
6 |
결과를 보고 마무리 짓고 대회에 입상한 상위 3개팀의 분석 결과를 학습 |
|
- 부족했던 점과 보완하면 좋은점 |
|
|
- 접근 법의 차이와 결과물을 어떻게 시각화 하였는지 등등 비교해보기 |
- |
|
투수 - 외국 경기 평균 변환
외국인메이저성적에 평균 구속과 구종 개수 추가
외국인메이저성적.head()
|
pitcher_name |
year |
ERA |
WAR |
TBF |
H |
HR |
BB |
HBP |
SO |
WHIP |
BABIP |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
0 |
오간도 |
2011.0 |
3.51 |
3.3 |
693.0 |
149.0 |
16.0 |
43.0 |
7.0 |
126.0 |
1.14 |
0.265 |
3.65 |
0.237 |
0.364 |
0.674 |
0.147 |
0.090 |
0.475 |
1 |
험버 |
2011.0 |
3.75 |
3.2 |
676.0 |
151.0 |
14.0 |
41.0 |
6.0 |
116.0 |
1.18 |
0.275 |
3.58 |
0.168 |
0.471 |
0.458 |
0.094 |
0.092 |
0.463 |
2 |
루카스 |
2012.0 |
3.76 |
2.8 |
827.0 |
185.0 |
13.0 |
78.0 |
1.0 |
140.0 |
1.36 |
0.289 |
3.75 |
0.203 |
0.572 |
0.707 |
0.082 |
0.062 |
0.424 |
3 |
다이아몬드 |
2012.0 |
3.54 |
2.2 |
714.0 |
184.0 |
17.0 |
31.0 |
4.0 |
90.0 |
1.24 |
0.292 |
3.94 |
0.210 |
0.534 |
0.597 |
0.040 |
0.068 |
0.467 |
4 |
듀브론트 |
2013.0 |
4.32 |
2.2 |
705.0 |
161.0 |
13.0 |
71.0 |
5.0 |
139.0 |
1.43 |
0.310 |
3.78 |
0.199 |
0.456 |
0.633 |
0.127 |
0.077 |
0.434 |
평균구속 = df.groupby('pitcher_name',as_index=False).agg({'km변환':'mean'})\
.sort_values('km변환',ascending=False).reset_index(drop=True)
for idx, value in 평균구속.iterrows():
for i in range(외국인메이저성적.shape[0]):
if 외국인메이저성적.loc[i,'pitcher_name'] == value[0]:
외국인메이저성적.loc[i,'평균구속'] = value[1]
외국인메이저성적[외국인메이저성적['평균구속'].isna() == True]
|
pitcher_name |
year |
ERA |
WAR |
TBF |
H |
HR |
BB |
HBP |
SO |
WHIP |
BABIP |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
평균구속 |
67 |
벨레스터 |
2010.0 |
2.57 |
0.1 |
89.0 |
15.0 |
2.0 |
11.0 |
2.0 |
28.0 |
1.24 |
0.283 |
3.51 |
0.114 |
0.568 |
0.622 |
0.071 |
0.145 |
0.420 |
NaN |
106 |
카스티요 |
2017.0 |
13.50 |
0.0 |
8.0 |
3.0 |
0.0 |
1.0 |
0.0 |
2.0 |
3.00 |
0.600 |
2.41 |
0.600 |
0.400 |
0.500 |
0.000 |
0.200 |
0.467 |
NaN |
139 |
리즈 |
2015.0 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
1.63 |
0.367 |
4.98 |
0.349 |
0.349 |
0.690 |
0.158 |
0.103 |
0.461 |
NaN |
171 |
벨레스터 |
2015.0 |
7.47 |
-0.3 |
77.0 |
17.0 |
3.0 |
13.0 |
1.0 |
13.0 |
1.91 |
0.298 |
6.64 |
0.160 |
0.280 |
0.718 |
0.071 |
0.104 |
0.429 |
NaN |
180 |
벨레스터 |
2011.0 |
4.54 |
-0.4 |
159.0 |
38.0 |
7.0 |
14.0 |
1.0 |
34.0 |
1.46 |
0.301 |
4.93 |
0.194 |
0.417 |
0.691 |
0.048 |
0.072 |
0.427 |
NaN |
190 |
벨레스터 |
2012.0 |
6.50 |
-0.5 |
83.0 |
14.0 |
5.0 |
11.0 |
3.0 |
12.0 |
1.39 |
0.173 |
7.71 |
0.161 |
0.321 |
0.684 |
0.069 |
0.077 |
0.418 |
NaN |
- 외국인 메이저 성적 df에 평균 구속 데이터를 추가헀다.
- 거기서 nan값을 가진 정보를 찾아서 스탯 테이터에서도 값이 없으면 지우는 방향으로 가려고 한다. 이걸 또 평균내야 하니 해당 연도를 제외한 평균을 삽입하거나 하려고 한다.
for val in 외국인메이저성적[외국인메이저성적['평균구속'].isna() == True].drop_duplicates(['pitcher_name'])['pitcher_name']:
display(df[df['pitcher_name'] == val])
|
game_date |
release_speed |
batter |
pitcher |
events |
description |
zone |
stand |
p_throws |
bb_type |
... |
ax |
ay |
az |
launch_speed |
launch_angle |
release_spin_rate |
pitch_name |
pitcher_name |
km변환 |
type |
0 rows × 26 columns
|
game_date |
release_speed |
batter |
pitcher |
events |
description |
zone |
stand |
p_throws |
bb_type |
... |
ax |
ay |
az |
launch_speed |
launch_angle |
release_spin_rate |
pitch_name |
pitcher_name |
km변환 |
type |
0 rows × 26 columns
|
game_date |
release_speed |
batter |
pitcher |
events |
description |
zone |
stand |
p_throws |
bb_type |
... |
ax |
ay |
az |
launch_speed |
launch_angle |
release_spin_rate |
pitch_name |
pitcher_name |
km변환 |
type |
0 rows × 26 columns
- 선수들의 정보를 찾아보려고 했는데 없어서 0으로 두고 하려고 한다.
외국인메이저성적_drop_year = 외국인메이저성적.drop('year', axis=1)
외국인메이저성적_drop_year.groupby('pitcher_name').agg('mean').head()
|
ERA |
WAR |
TBF |
H |
HR |
BB |
HBP |
SO |
WHIP |
BABIP |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
평균구속 |
pitcher_name |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
니퍼트 |
4.290000 |
-0.300000 |
262.000000 |
61.0 |
7.000000 |
34.000000 |
5.000000 |
47.000000 |
1.680 |
0.320000 |
5.090000 |
0.267000 |
0.320000 |
0.666000 |
0.099000 |
0.082000 |
0.42300 |
143.882653 |
다이아몬드 |
10.262500 |
0.550000 |
369.500000 |
100.0 |
10.250000 |
21.500000 |
1.250000 |
40.250000 |
2.125 |
0.333750 |
5.660000 |
0.208250 |
0.466250 |
0.641250 |
0.044250 |
0.059000 |
0.44025 |
139.498235 |
듀브론트 |
5.106667 |
0.616667 |
377.666667 |
90.0 |
10.500000 |
36.500000 |
2.333333 |
73.666667 |
1.560 |
0.317833 |
4.548333 |
0.205167 |
0.442667 |
0.632167 |
0.104333 |
0.077500 |
0.42850 |
141.691396 |
레나도 |
7.306667 |
-0.500000 |
131.333333 |
31.0 |
7.333333 |
14.666667 |
0.333333 |
14.666667 |
1.630 |
0.263667 |
6.703333 |
0.173000 |
0.345667 |
0.618000 |
0.101000 |
0.052667 |
0.45400 |
141.203608 |
레온 |
6.050000 |
-0.100000 |
63.000000 |
16.5 |
2.000000 |
5.000000 |
0.000000 |
10.500000 |
1.585 |
0.303500 |
6.235000 |
0.162500 |
0.479500 |
0.590500 |
0.034500 |
0.101500 |
0.47250 |
140.058685 |
- 선수들의 평균을 내려고 연도를 제거하고 묶었다.
- 소수점 이하 자리는 다시 조정해서 df로 만들자
외국인메이저_평균 = 외국인메이저성적_drop_year.groupby('pitcher_name').agg('mean').head().reset_index(drop=False).round(decimals=2)
playername = list(throw_df['pitcher_name'].drop_duplicates())
구종데이터 = pd.DataFrame({'pitcher_name':[], '2-Seam Fastball':[],'4-Seam Fastball':[],'Changeup':[],'Curveball':[],
'Cutter':[],'Intentional Ball':[],'Pitch Out':[],'Slider':[]})
for name in playername:
try:
a = 외국인스탯캐스터.groupby(['pitcher_name','pitch_name']).agg({'pitch_name':'count'})\
.T[name].reset_index(drop=True)
a['pitcher_name'],a['cnt'] = name, a.shape[1]
구종데이터 = 구종데이터.append(a,ignore_index=True)
except:
print(name)
display(구종데이터.head())
print(구종데이터.cnt.mean())
|
2-Seam Fastball |
4-Seam Fastball |
Changeup |
Curveball |
Cutter |
Eephus |
Fastball |
Forkball |
Intentional Ball |
Pitch Out |
Sinker |
Slider |
Split Finger |
Unknown |
cnt |
pitcher_name |
0 |
26.0 |
384.0 |
81.0 |
82.0 |
6.0 |
NaN |
NaN |
NaN |
4.0 |
1.0 |
NaN |
4.0 |
NaN |
NaN |
8.0 |
니퍼트 |
1 |
19.0 |
245.0 |
8.0 |
NaN |
20.0 |
NaN |
NaN |
NaN |
4.0 |
2.0 |
269.0 |
306.0 |
NaN |
NaN |
8.0 |
소사 |
2 |
58.0 |
433.0 |
429.0 |
NaN |
171.0 |
NaN |
NaN |
NaN |
9.0 |
5.0 |
1360.0 |
284.0 |
NaN |
NaN |
8.0 |
탈보트 |
3 |
773.0 |
950.0 |
297.0 |
88.0 |
NaN |
NaN |
NaN |
NaN |
NaN |
3.0 |
NaN |
256.0 |
NaN |
NaN |
6.0 |
레이예스 |
4 |
207.0 |
324.0 |
182.0 |
25.0 |
NaN |
NaN |
NaN |
NaN |
1.0 |
NaN |
NaN |
153.0 |
NaN |
NaN |
6.0 |
세든 |
투수이름 = 구종데이터['pitcher_name']
구종데이터 = 구종데이터.loc[:,구종데이터.columns != 'pitcher_name'].fillna(0).astype(int)
구종데이터['pitcher_name'] = 투수이름
구종데이터.head()
|
2-Seam Fastball |
4-Seam Fastball |
Changeup |
Curveball |
Cutter |
Eephus |
Fastball |
Forkball |
Intentional Ball |
Pitch Out |
Sinker |
Slider |
Split Finger |
Unknown |
cnt |
pitcher_name |
0 |
26 |
384 |
81 |
82 |
6 |
0 |
0 |
0 |
4 |
1 |
0 |
4 |
0 |
0 |
8 |
니퍼트 |
1 |
19 |
245 |
8 |
0 |
20 |
0 |
0 |
0 |
4 |
2 |
269 |
306 |
0 |
0 |
8 |
소사 |
2 |
58 |
433 |
429 |
0 |
171 |
0 |
0 |
0 |
9 |
5 |
1360 |
284 |
0 |
0 |
8 |
탈보트 |
3 |
773 |
950 |
297 |
88 |
0 |
0 |
0 |
0 |
0 |
3 |
0 |
256 |
0 |
0 |
6 |
레이예스 |
4 |
207 |
324 |
182 |
25 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
153 |
0 |
0 |
6 |
세든 |
for idx, value in 구종데이터.iterrows():
for idx2, value2 in 외국인메이저_평균.iterrows():
if value['pitcher_name'] == value2['pitcher_name']:
외국인메이저_평균.loc[idx2, 'cnt'] = value['cnt']
|
pitcher_name |
ERA |
WAR |
TBF |
H |
HR |
BB |
HBP |
SO |
WHIP |
BABIP |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
평균구속 |
cnt |
0 |
니퍼트 |
4.29 |
-0.30 |
262.00 |
61.0 |
7.00 |
34.00 |
5.00 |
47.00 |
1.68 |
0.32 |
5.09 |
0.27 |
0.32 |
0.67 |
0.10 |
0.08 |
0.42 |
143.88 |
8.0 |
1 |
다이아몬드 |
10.26 |
0.55 |
369.50 |
100.0 |
10.25 |
21.50 |
1.25 |
40.25 |
2.12 |
0.33 |
5.66 |
0.21 |
0.47 |
0.64 |
0.04 |
0.06 |
0.44 |
139.50 |
6.0 |
2 |
듀브론트 |
5.11 |
0.62 |
377.67 |
90.0 |
10.50 |
36.50 |
2.33 |
73.67 |
1.56 |
0.32 |
4.55 |
0.21 |
0.44 |
0.63 |
0.10 |
0.08 |
0.43 |
141.69 |
7.0 |
3 |
레나도 |
7.31 |
-0.50 |
131.33 |
31.0 |
7.33 |
14.67 |
0.33 |
14.67 |
1.63 |
0.26 |
6.70 |
0.17 |
0.35 |
0.62 |
0.10 |
0.05 |
0.45 |
141.20 |
4.0 |
4 |
레온 |
6.05 |
-0.10 |
63.00 |
16.5 |
2.00 |
5.00 |
0.00 |
10.50 |
1.58 |
0.30 |
6.24 |
0.16 |
0.48 |
0.59 |
0.03 |
0.10 |
0.47 |
140.06 |
5.0 |
- 마지막 열에 cnt가 추가 되었다. 이제 이 데이터에 한국 승,패를 넣어서 학습해보자.
throw_df_copy = throw_df.copy()
throw_df_copy = throw_df_copy[['pitcher_name','year','승','패']]
외국인_승패_추가 = throw_df_copy.merge(외국인메이저_평균, how='left', on='pitcher_name')
외국인_승패_추가.head()
|
pitcher_name |
year |
승 |
패 |
ERA |
WAR |
TBF |
H |
HR |
BB |
... |
BABIP |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
평균구속 |
cnt |
0 |
리즈 |
2011 |
11 |
13 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
... |
0.37 |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.10 |
0.46 |
NaN |
NaN |
1 |
니퍼트 |
2011 |
15 |
6 |
4.29 |
-0.3 |
262.0 |
61.0 |
7.0 |
34.0 |
... |
0.32 |
5.09 |
0.27 |
0.32 |
0.67 |
0.10 |
0.08 |
0.42 |
143.88 |
8.0 |
2 |
니퍼트 |
2012 |
11 |
10 |
4.29 |
-0.3 |
262.0 |
61.0 |
7.0 |
34.0 |
... |
0.32 |
5.09 |
0.27 |
0.32 |
0.67 |
0.10 |
0.08 |
0.42 |
143.88 |
8.0 |
3 |
리즈 |
2012 |
5 |
12 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
... |
0.37 |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.10 |
0.46 |
NaN |
NaN |
4 |
소사 |
2012 |
9 |
8 |
5.23 |
0.2 |
231.0 |
54.0 |
7.0 |
23.0 |
... |
0.29 |
4.77 |
0.18 |
0.44 |
0.62 |
0.15 |
0.09 |
0.45 |
144.06 |
8.0 |
- 외국인 승패 기록과 평균 기록을 합쳤다.
- NaN값은 평균으로 바꾸려고 한다.
외국인_승패_추가_승 = 외국인_승패_추가['승']
외국인_승패_추가_패 = 외국인_승패_추가['패']
외국인_승패_추가_승패제거 = 외국인_승패_추가.drop(['승','패'],axis=1)
외국인_승패_추가_승.isnull().values.any()
- 이렇게 하나씩 null값을 확인하고 변경해준다.
외국인_승패_추가_승패제거[외국인_승패_추가_승패제거['ERA'].isnull()]
pitcher_name |
year |
ERA |
WAR |
TBF |
H |
HR |
BB |
HBP |
SO |
... |
BABIP |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
평균구속 |
cnt |
|
0 |
리즈 |
2011 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
... |
0.37 |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.1 |
0.46 |
NaN |
NaN |
3 |
리즈 |
2012 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
... |
0.37 |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.1 |
0.46 |
NaN |
NaN |
6 |
리즈 |
2013 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
... |
0.37 |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.1 |
0.46 |
NaN |
NaN |
12 |
밴덴헐크 |
2013 |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
... |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
18 |
밴덴헐크 |
2014 |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
... |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
56 |
카스티요 |
2016 |
13.50 |
0.0 |
8.0 |
3.0 |
0.0 |
1.0 |
0.0 |
2.0 |
... |
0.60 |
2.41 |
0.60 |
0.40 |
0.50 |
0.00 |
0.2 |
0.47 |
NaN |
NaN |
58 |
마리몬 |
2016 |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
... |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
76 |
브리검 |
2017 |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
... |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
91 |
브리검 |
2018 |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
... |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
- 모두 nan값인 행들은 날려버리고 평균 구속과 cnt만 nan인 것은 평균값으로 대체하자.
- 그 다음 이름을 모두 인코딩하여 머신러닝을 해보자.
- 우선 리즈는 구글에 검색했을 때 평균 150km/h라고 해서 이 수치를 넣으려고 한다.
- 카스티요는 패스트볼 157km/h, 체인지업은 140km/h, 슬라이더는 136km/h라고 나온다. 3개를 평균내서 기입하자. 144km/h 나온다.
리즈, 카스티요 값 변경한 후 cnt도 평균으로 바꿔주기
def change_구속(df):
if df['pitcher_name'] == '리즈':
return 150
elif df['pitcher_name'] == '카스티요':
return 144
else:
return df['평균구속']
외국인_승패_추가_승패제거['평균구속'] = 외국인_승패_추가_승패제거.apply(lambda x:change_구속(x), axis=1)
외국인_승패_추가_승패제거 = 외국인_승패_추가_승패제거.fillna(외국인_승패_추가_승패제거.mean())
외국인_승패_추가_승패제거['cnt'] = 외국인_승패_추가_승패제거['cnt'].astype('int')
외국인_승패_추가_승패제거.head()
- 리즈와 카스티요만 다른 값을 주기 위해 apply 함수를 써서 평균 구속값을 넣었다.
- cnt값도 cnt 평균값으로 대체했다.
|
pitcher_name |
year |
ERA |
WAR |
TBF |
H |
HR |
BB |
HBP |
SO |
... |
BABIP |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
평균구속 |
cnt |
0 |
리즈 |
2011 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
... |
0.37 |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.10 |
0.46 |
150.00 |
6 |
1 |
니퍼트 |
2011 |
4.29 |
-0.3 |
262.0 |
61.0 |
7.0 |
34.0 |
5.0 |
47.0 |
... |
0.32 |
5.09 |
0.27 |
0.32 |
0.67 |
0.10 |
0.08 |
0.42 |
143.88 |
8 |
2 |
니퍼트 |
2012 |
4.29 |
-0.3 |
262.0 |
61.0 |
7.0 |
34.0 |
5.0 |
47.0 |
... |
0.32 |
5.09 |
0.27 |
0.32 |
0.67 |
0.10 |
0.08 |
0.42 |
143.88 |
8 |
3 |
리즈 |
2012 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
... |
0.37 |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.10 |
0.46 |
150.00 |
6 |
4 |
소사 |
2012 |
5.23 |
0.2 |
231.0 |
54.0 |
7.0 |
23.0 |
3.0 |
38.0 |
... |
0.29 |
4.77 |
0.18 |
0.44 |
0.62 |
0.15 |
0.09 |
0.45 |
144.06 |
8 |
- 이제 선수 이름만 라벨 인코딩으로 변경한 후 의사결정 나무를 진행하면 된다.
라벨인코딩
from sklearn.preprocessing import LabelEncoder
def label(df):
col = list(df)
encoder = LabelEncoder()
encoder.fit(col)
col_label = encoder.transform(col)
return col_label
pitcher_name_label = label(외국인_승패_추가_승패제거['pitcher_name'])
외국인_승패_추가_승패제거 = 외국인_승패_추가_승패제거.assign(pitcher_name_label=pitcher_name_label)
외국인_승패_추가_승패제거_digit = 외국인_승패_추가_승패제거.drop(['pitcher_name'],axis=1)
외국인_승패_추가_승패제거_digit.head()
- 라벨을 새로운 컬럼으로 추가하고 기존에 있던 선수 이름 컬럼을 제거한다.
|
year |
ERA |
WAR |
TBF |
H |
HR |
BB |
HBP |
SO |
WHIP |
... |
FIP |
LD% |
GB% |
FB% |
IFFB% |
SwStr% |
Swing% |
평균구속 |
cnt |
pitcher_name_label |
0 |
2011 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
1.63 |
... |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.10 |
0.46 |
150.00 |
6 |
9 |
1 |
2011 |
4.29 |
-0.3 |
262.0 |
61.0 |
7.0 |
34.0 |
5.0 |
47.0 |
1.68 |
... |
5.09 |
0.27 |
0.32 |
0.67 |
0.10 |
0.08 |
0.42 |
143.88 |
8 |
0 |
2 |
2012 |
4.29 |
-0.3 |
262.0 |
61.0 |
7.0 |
34.0 |
5.0 |
47.0 |
1.68 |
... |
5.09 |
0.27 |
0.32 |
0.67 |
0.10 |
0.08 |
0.42 |
143.88 |
8 |
0 |
3 |
2012 |
4.24 |
-0.2 |
106.0 |
26.0 |
4.0 |
12.0 |
3.0 |
27.0 |
1.63 |
... |
4.98 |
0.35 |
0.35 |
0.69 |
0.16 |
0.10 |
0.46 |
150.00 |
6 |
9 |
4 |
2012 |
5.23 |
0.2 |
231.0 |
54.0 |
7.0 |
23.0 |
3.0 |
38.0 |
1.44 |
... |
4.77 |
0.18 |
0.44 |
0.62 |
0.15 |
0.09 |
0.45 |
144.06 |
8 |
25 |
의사결정나무
feature = 외국인_승패_추가_승패제거_digit
label = 외국인_승패_추가_승
X_train, X_test, y_train, y_test = train_test_split(feature,label, test_size = 0.2, random_state=20)
base_dtc = DecisionTreeClassifier(random_state=20, criterion='entropy')
base_dtc.fit(X_train, y_train)
predition = base_dtc.predict(X_test)
print(' y_test\n', y_test)
print(' prediction\n', predition)
>
y_test
72 12
78 10
31 19
5 14
2 11
46 4
38 13
100 9
93 7
0 11
39 7
60 7
81 5
12 7
98 6
36 10
48 18
23 5
65 2
53 10
92 9
Name: 승, dtype: int64
prediction
[ 5 11 13 15 15 6 6 2 11 5 5 6 10 13 13 15 3 6 7 10 11]
from sklearn.metrics import accuracy_score
print(f'예측 정확도 : {accuracy_score(y_test, predition)}')
>
예측 정확도 : 0.047619047619047616
하면서 뭔가를 잘못했다는 느낌이 왔다. 다시 의사결정나무가 어떻게 동작하는지 살펴봐야겠다.
데이터 정제를 다시 살펴보고 예측 모델 생성부터 다시 해보자.
머신러닝 책에 나와있는 의사결정 나무를 공부하고 다시 해봐야겠다.