naufalbudianto28 commited on
Commit
4d48d76
1 Parent(s): 3d32207

Upload 7 files

Browse files
Files changed (7) hide show
  1. P1M2_naufal.ipynb +0 -0
  2. app.py +10 -0
  3. bank-full.csv +0 -0
  4. best_model_xgb.pkl +3 -0
  5. eda.py +233 -0
  6. prediction.py +89 -0
  7. requirements.txt +8 -0
P1M2_naufal.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import stremlit as st
2
+ import eda
3
+ import prediction
4
+
5
+ page = st.sidebar.selectbox('Pilih Halaman: ', ('EDA', 'Prediction'))
6
+
7
+ if page == 'EDA':
8
+ eda.run()
9
+ else:
10
+ prediction.run()
bank-full.csv ADDED
The diff for this file is too large to render. See raw diff
 
best_model_xgb.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c5229aa2c3dfee96c1aa3cb4b9dcdd1b81481283a3a177db7cce8d48f2ae274e
3
+ size 158942
eda.py ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import seaborn as sns
4
+ import matplotlib.pyplot as plt
5
+ from scipy.stats import kendalltau
6
+
7
+ def run():
8
+ st.title('Eksplorasi Data pada Dataset Telemarketing Deposito Bank Portugis')
9
+
10
+ data = pd.read_csv("/Users/Naufal's/Desktop/Hacktiv8 Tugas/p1-ftds031-rmt-m2-naufalbudianto28/bank-full.csv", sep=';')
11
+ st.dataframe(data)
12
+
13
+ st.subheader('Basic Data Distribution')
14
+
15
+ st.write('#### 1. Age Distribution')
16
+ fig, ax = plt.subplots(figsize=(18, 6))
17
+ age_bar = data['age'].value_counts().sort_index().plot(kind='bar', color='skyblue', ax=ax)
18
+ ax.set_title('Age Distribution')
19
+ ax.set_xlabel('Age')
20
+ ax.set_ylabel('Count')
21
+ ax.set_xticks(range(len(data['age'].unique())))
22
+ ax.set_xticklabels(data['age'].unique(), rotation=45)
23
+
24
+ for p in age_bar.patches:
25
+ age_bar.annotate(str(p.get_height()), (p.get_x() + p.get_width() / 2., p.get_height()),
26
+ ha='center', va='center', xytext=(0, 5), textcoords='offset points')
27
+ plt.tight_layout()
28
+ st.pyplot(fig)
29
+ st.write('Dari hasil visualisasi data di atas, dapat disimpulkan bahwa mayoritas klien Bank Portugis didominasi oleh Early Adults (usia 25-35 tahun), dimana merupakan masa-masa produktif mayoritas orang. Mid-Adults (usia 36-45 tahun), dimana mayoritas orang sudah berkeluarga dan memiliki posisi mid-level pada karir. Dan Late-Adults (usia 46-60 tahun), dimana mayoritas orang mengalami masa puncak karir dan sudah bersiap untuk memasuki masa pensiun.')
30
+
31
+ ###
32
+ st.write('#### 2. Job Distribution')
33
+ fig, ax = plt.subplots(figsize=(10, 6))
34
+ # Melakukan ploting bar terhadap distribusi jenis pekerjaan dan diurutkan dari nilai terbesar.
35
+ group_job = data['job'].value_counts().sort_values(ascending=False)
36
+ group_job.plot(kind='bar', ax=ax)
37
+ ax.set_title('Job Distribution')
38
+ ax.set_xlabel('Job')
39
+ ax.set_ylabel('Distribution')
40
+ # Menampilkan nilai tiap bar dengan fungsi looping.
41
+ for bar in ax.patches:
42
+ yval = bar.get_height()
43
+ ax.text(bar.get_x() + bar.get_width() / 2, yval, round(yval, 2), va='bottom')
44
+ plt.tight_layout()
45
+ st.pyplot(fig)
46
+ st.write('Selaras dengan hasil analisa visual pada distribusi umur klien, pada dataset klien Bank Portugis menunjukkan bahwa mayoritas klien mereka adalah pekerja (Adults - usia produktif). Namun jika diperhatikan dari visualisasi di atas, ada beberapa kejanggalan yaitu adanya typo pada tipe pekerjaan dengan value `admin.` yang seharusnya adalah `admin`. Terdapat tipe pekerjaan `unknown` yang dimana seharusnya **sudah terisi** untuk keperluan administrasi Bank Portugis. Maka beberapa kejanggalan di atas akan saya tangani saat proses Feature Engineering.')
47
+
48
+ ###
49
+ st.write('#### 3. Marital Status Distribution')
50
+ marital_counts = data['marital'].value_counts()
51
+ # Melakukan ploting pie-chart pada distribusi marital status.
52
+ fig, ax = plt.subplots(figsize=(6, 6))
53
+ ax.pie(marital_counts, labels=marital_counts.index, autopct='%1.2f%%', startangle=140)
54
+ ax.set_title('Marital Status')
55
+ ax.axis('equal')
56
+ plt.tight_layout()
57
+ st.pyplot(fig)
58
+ st.write('Hasil analisa visual pada status pernikahan menunjukkan bahwa klien Bank Portugis didominasi oleh orang yang sudah berkeluarga. Selaras dengan analisa pada distribusi umur dan tipe pekerjaan, dimana didominasi oleh umur 30-40 tahun yang di mayoritas masyarakat pada umumnya sudah berkeluarga, terlihat dari hasil analisa status pernikahan didominasi oleh **married** dengan `60,2%` kemudian **single** dengan jumlah `28,3%`.')
59
+
60
+ ###
61
+ st.write('#### 4. Education Background Distribution')
62
+ ed_counts = data['education'].value_counts()
63
+ fig, ax = plt.subplots(figsize=(6, 6))
64
+ ax.pie(ed_counts, labels=ed_counts.index, autopct='%1.2f%%', startangle=140)
65
+ ax.set_title('Educational Background')
66
+ ax.axis('equal')
67
+ plt.tight_layout()
68
+ st.pyplot(fig)
69
+ st.write('Data educational background memiliki value primary (SD), secondary (SMP-SMA/SMK), dan tertiary (Kuliah). Dimana dari hasil eksplorasi visual didapatkan klien Bank Portugis didominasi oleh secondary (51,3%) dan tertiary (29,4%) educational background. Selaras dengan hasil visualisasi tipe pekerjaan, bahwa klien didominasi oleh blue-collar (merupakan buruh pekerja industri manual) yang mayoritas adalah lulusan SMK (secondary).')
70
+ st.write('Namun hasil eksplorasi ini juga menunjukkan **kejanggalan**, yaitu adanya value `unknown` pada data educational background. Seharusnya dikarenakan ini termasuk biodata pribadi dan merupakan syarat administrasi, secara logika tidak ada educational background bernilai unknown pada dataset. Maka nantinya baris-baris yang memiliki value `unknown` pada educational background akan saya hapus disaat melakukan proses feature engineering.')
71
+
72
+ ###
73
+ st.write('#### 4. Balance Distribution')
74
+ bins = [-float('inf'), 0, 25000, 50000, float('inf')]
75
+ labels = ['Minus', '0 - 25,000', '25,000 - 50,000', '>= 50,000']
76
+
77
+ data['balance_category'] = pd.cut(data['balance'], bins=bins, labels=labels, right=False)
78
+ balance_distribution = data['balance_category'].value_counts().sort_index()
79
+
80
+ fig, ax = plt.subplots(figsize=(10, 6))
81
+ balance_distribution.plot(kind='bar', color='green', width=0.8, ax=ax)
82
+ for i, v in enumerate(balance_distribution):
83
+ ax.text(i, v + 50, str(v), ha='center', va='bottom', fontsize=10)
84
+
85
+ ax.set_title('Balance Distribution')
86
+ ax.set_xlabel('Range of Balance (€)')
87
+ ax.set_ylabel('Count')
88
+ ax.set_xticklabels(labels, rotation=45)
89
+ plt.tight_layout()
90
+ st.pyplot(fig)
91
+ st.write('Hasil analisa visual pada distribusi rata-rata saldo para klien Bank Portugis menunjukkan mayoritas klien memiliki rata-rata saldo di bank dengan range €0-25,000 dengan presentase 91,5%.')
92
+ st.write('Dan ditemukan insight menarik yaitu visualisasi menunjukkan bahwa ada 8,3% klien yang memiliki saldo minus (< €0). Hal ini bisa disebabkan oleh beberapa faktor, seperti kemungkinan **gagal bayar** atau kredit macet, mengingat Bank Portugis juga menyediakan layanan kartu kredit, pinjaman personal, dan cicilan rumah. Dan atau **tidak ada pemasukan** lalu terpotong biaya administrasi bulanan, jika dilihat dari hasil visualisasi pekerjaan ada ~8% klien yang tidak bekerja dan sudah pensiun.')
93
+
94
+ ###
95
+ st.write('#### 4. Credit and Loan Distribution')
96
+ default_counts = data['default'].value_counts()
97
+ housing_counts = data['housing'].value_counts()
98
+ loan_counts = data['loan'].value_counts()
99
+
100
+ fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 6))
101
+ ax1.pie(default_counts, labels=default_counts.index, autopct='%2.2f%%', startangle=140)
102
+ ax1.set_title('Have Credit?')
103
+ ax2.pie(housing_counts, labels=housing_counts.index, autopct='%2.2f%%', startangle=140)
104
+ ax2.set_title('Have Housing Loan?')
105
+ ax3.pie(loan_counts, labels=loan_counts.index, autopct='%2.2f%%', startangle=140)
106
+ ax3.set_title('Have Personal Loan?')
107
+ ax1.axis('equal')
108
+ ax2.axis('equal')
109
+ ax3.axis('equal')
110
+
111
+ plt.tight_layout()
112
+ st.pyplot(fig)
113
+ st.write('Grafik pie di atas menunjukkan presentase penggunaan layanan peminjaman/cicilan yang dimiliki Bank Portugis oleh para kliennya. Dimana layanan cicilan rumah paling diminati oleh para klien Bank Portugis dengan presentase 55,6% pengguna. Secara logis hal ini sesuai dengan demografi klien Bank Portugis yang mayoritas adalah perkerja dan sudah berkeluarga, dimana pasti ada kebutuhan untuk memiliki tempat tinggal yang layak bagi keluarga mereka.')
114
+
115
+ ###
116
+ st.subheader('Telemarketing Data Distribution')
117
+ st.write('#### 1. Telemarketing Type Distribution')
118
+
119
+ tc_counts = data['contact'].value_counts()
120
+ fig, ax = plt.subplots(figsize=(6, 6))
121
+ ax.pie(tc_counts, labels=tc_counts.index, autopct='%2.2f%%', startangle=140)
122
+ ax.set_title('Type of Telemarketing Contact')
123
+ ax.axis('equal')
124
+ plt.tight_layout()
125
+ st.pyplot(fig)
126
+ st.write('Visualisasi di atas menunjukkan tentang tipe usaha telemarketing yang Tim Telemarketing Bank Portugis lakukan untuk melakukan tawaran campaign-campaign yang mereka miliki, jika dilihat bahwa klien mereka cenderung lebih aktif / responsif melalui telfon seluler (HP) dengan nilai 65% dibandingkan dengan telfon rumah yang bernilai 6,4%. Namun juga terdapat tipe telemarketing unknown, hal ini bisa disebabkan oleh data pada klien yang belum pernah dihubungi atau dilakukan campaign, sehingga bernilai unknown. Pada data ini nantinya tidak akan saya tangani terkait value unknown pada kolom contact, dikarenakan untuk menunjukkan keaslian data yang berpengaruh kepada insight Tim Telemarketing.')
127
+
128
+ ###
129
+ st.write('#### 2. Duration of The Contact Distribution')
130
+ bins = [-float('inf'), 60, 900, 1800, 2700, 3600, float('inf')]
131
+ labels = ['0 - 1 minute', '1 - 15 minutes', '15 - 30 minutes',
132
+ '30 - 45 minutes', '45 - 60 minutes', '>= 60 minutes']
133
+
134
+ data['dur_category'] = pd.cut(data['duration'], bins=bins, labels=labels, right=False)
135
+ dur_distribution = data['dur_category'].value_counts().sort_index()
136
+
137
+ fig, ax = plt.subplots(figsize=(10, 6))
138
+ dur_distribution.plot(kind='bar', color='purple', width=0.8, ax=ax)
139
+
140
+ for i, v in enumerate(dur_distribution):
141
+ ax.text(i, v + 50, str(v), ha='center', va='bottom', fontsize=10)
142
+
143
+ ax.set_title('Call Duration Distribution')
144
+ ax.set_xlabel('Call Duration')
145
+ ax.set_ylabel('Count')
146
+ ax.set_xticklabels(labels, rotation=45)
147
+ plt.tight_layout()
148
+ st.pyplot(fig)
149
+ st.write('Terlihat dari hasil eksplorasi visual terhadap kolom durasi waktu telfon terakhir yang dilakukan Tim Telemarketing Bank Portugis, bahwa mayoritas telfon yang mereka lakukan dengan klien adalah kurang dari 30 menit. Hal ini menunjukkan bahwa mayoritas dari klien mereka adalah orang yang sibuk (tidak punya banyak waktu), mengingat hal ini juga ditunjukkan dari hasil eksplorasi pekerjaan dan umur, bahwa klien mereka merupakan usia produktif bekerja. Namun ada hal menarik pada grafik bahwa terdapat sekitar 4659 telfon dengan durasi 0 hingga 1 menit, hal ini menunjukkan bahwa ada beberapa telfon yang belum dilakukan oleh Tim kepada klien, dan atau penolakan telfon.')
150
+
151
+ ###
152
+ st.write('#### 3. Number of Campaign Calls Distribution')
153
+ call_distribution = data['age'].value_counts().sort_index()
154
+
155
+ fig, ax = plt.subplots(figsize=(18, 6))
156
+ call_bar = call_distribution.plot(kind='bar', color='magenta', ax=ax)
157
+
158
+ ax.set_title('Number of Calls Distribution')
159
+ ax.set_xlabel('Number of Calls')
160
+ ax.set_ylabel('Count')
161
+ ax.set_xticklabels(call_distribution.index, rotation=45)
162
+
163
+ for c in call_bar.patches:
164
+ ax.annotate(str(c.get_height()), (c.get_x() + c.get_width() / 2., c.get_height()),
165
+ ha='center', va='center', xytext=(0, 5), textcoords='offset points')
166
+
167
+ plt.tight_layout()
168
+ st.pyplot(fig)
169
+ st.write('Visualisasi di atas merupakan distribusi jumlah telfon yang dilakukan Tim Telemarketing terhadap para klien dalam kurun waktu 1 tahun. Hasil grafik bisa jadi menunjukkan terhubung atau tidak terhubungnya suatu usaha telfon yang dilakukan Tim Telemarketing mereka.')
170
+ st.write('Dan ada juga kemungkinan tiap individu Tim Telemarketing membatasi maksimum usaha menelfon nya. Contoh; si X membatasi maksimum jumlah call ke klien Y sebanyak 30x telfon dalam satu tahun, sehingga ketika sudah mencapai batas tersebut dan tidak ada jawaban, maka X memberikan status unknown pada CRM mereka, hal ini lazim terjadi pada Tim Sales di semua industri.')
171
+
172
+ ###
173
+ st.write('#### 4. Previous Campaign Result')
174
+ pc_counts = data['poutcome'].value_counts()
175
+
176
+ fig, ax = plt.subplots(figsize=(6, 7))
177
+ ax.pie(pc_counts, labels=pc_counts.index, autopct='%2.2f%%', startangle=140)
178
+ ax.set_title('Previous Campaign Result')
179
+ ax.axis('equal')
180
+ plt.tight_layout()
181
+ st.pyplot(fig)
182
+ st.write('Pie Chart di atas menunjukkan hasil dari campaign sebelumnya tentang layanan/produk berbeda, dengan menghasilkan output mayoritas bernilai unknown, dimana ada kemungkinan hal ini terjadi karena Telfon tidak di respon oleh klien, Nomor tidak bisa dihubungi oleh Tim Telemarketing, Telemarketing terblokir oleh klien, dan atau Klien belum dihubungi oleh Telemarketing. Sehingga mereka melakukan update status pada CRM mereka dengan nilai `unknown`')
183
+
184
+ ###
185
+ st.subheader('Correlation between Feature and Target')
186
+ st.write('#### 1. Numerical Columns')
187
+ st.write('Pada tahap ini saya melihat heatmap korelasi Spearman (dengan asumsi masih terdapat outliers) terhadap kolom-kolom numerikal dan kolom target.')
188
+ # Membuat dataset dummy.
189
+ df_dummy = pd.get_dummies(data, columns=['y'], drop_first=True, dtype=int)
190
+ df_num = df_dummy[['age', 'balance', 'duration', 'campaign', 'day', 'pdays', 'previous', 'y_yes']]
191
+
192
+ fig, ax = plt.subplots(figsize=(10, 8))
193
+ sns.heatmap(df_num.corr(method='spearman'), annot=True, cmap='coolwarm', fmt=".2f", ax=ax)
194
+ ax.set_title("Numerical - Spearman Correlation")
195
+ st.pyplot(fig)
196
+ st.write('Untuk korelasi Spearman di atas saya menentukan threshold korelasi adalah corr >= |0,05|, untuk dikategorikan berkorelasi dengan target y_yes, sehingga fitur-fitur yang memiliki korelasi adalah: balance, duration, campaign, pdays, previous.')
197
+
198
+ ###
199
+ st.write('#### 2. Categorical Columns')
200
+ st.write('Pada tahap ini saya melihat heatmap korelasi Kendall terhadap kolom kategorikal dan kolom target.')
201
+
202
+ df_cat = df_dummy[['job', 'marital', 'contact', 'month', 'poutcome', 'education', 'default', 'housing', 'loan']]
203
+ cols_1 = []
204
+ corr_1 = []
205
+ pval_1 = []
206
+
207
+ for col in df_cat.columns:
208
+ corr_coef, p_value = kendalltau(df_cat[col], df_dummy['y_yes'])
209
+ cols_1.append(col)
210
+ corr_1.append(corr_coef)
211
+ pval_1.append(p_value)
212
+
213
+ corr_df = pd.DataFrame({'Nama Kolom': cols_1, 'Kendall Corr': corr_1, 'P-value': pval_1})
214
+ fig, ax = plt.subplots(figsize=(10, 6))
215
+ sns.heatmap(corr_df.set_index('Nama Kolom')[['Kendall Corr']].T, annot=True, cmap='coolwarm', cbar=True, ax=ax)
216
+ ax.set_title('Kendall Correlation Heatmap Between Features and Target')
217
+ st.pyplot(fig)
218
+ st.write('Untuk korelasi Kendall di atas saya menentukan threshold adalah corr >= |0,035|, untuk dikategorikan berkorelasi dengan target, sehingga fitur-fitur yang memiliki korelasi adalah: job, marital, education, contact, housing, loan, dan poutcome.')
219
+
220
+
221
+ ###
222
+ st.subheader('Target Proportion')
223
+ y_count = data['y'].value_counts()
224
+
225
+ fig, ax = plt.subplots(figsize=(6, 7))
226
+ ax.pie(y_count, labels=y_count.index, autopct='%2.2f%%', startangle=140)
227
+ ax.set_title('Target Proportion')
228
+ ax.axis('equal')
229
+ st.pyplot(fig)
230
+ st.write('Terlihat hasil dari program campaign Tim Telemarketing Bank Portugis tentang layanan deposito berjangka yang telah dilakukan selama satu tahun, memiliki mayoritas penolakan dengan nilai yang sangat dominan 88%. Diharapkan insight-insight yang didapatkan dari proses eksplorasi data dapat menjadi acuan dan bahan evaluasi Tim Telemarketing kedepannya.')
231
+
232
+ if __name__ == '__main__':
233
+ run()
prediction.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import matplotlib.pyplot as plt
4
+ import pickle
5
+
6
+ # Load Best Model
7
+ with open('best_model_xgb.pkl', 'rb') as xgb_file:
8
+ best_model_xgb = pickle.load(xgb_file)
9
+
10
+ def run():
11
+ st.title('Klasifikasi XGBoost pada Telemarketing Deposito')
12
+
13
+ with st.form('telemarketing_deposit'):
14
+ st.write('### Masukkan Data Klien')
15
+
16
+ # Job
17
+ job_options = ['bluecollar', 'management', 'technician', 'admin', 'services', 'retired', 'self-employed', 'entrepreneur', 'unemployed', 'housemaid', 'student']
18
+ job = st.selectbox('Pekerjaan', job_options)
19
+
20
+ # Marital status
21
+ marital_status_options = ['single', 'divorced', 'married']
22
+ marital_status = st.radio('Status Pernikahan', marital_status_options)
23
+
24
+ # Education
25
+ education_options = ['primary', 'secondary', 'tertiary']
26
+ education = st.radio('Pendidikan', education_options)
27
+
28
+ # Balance
29
+ balance = st.number_input('Saldo Rata-rata (€)', min_value=0)
30
+
31
+ # Housing loan
32
+ housing_loan_options = ['yes', 'no']
33
+ housing_loan = st.checkbox('Punya Pinjaman Rumah?', housing_loan_options)
34
+
35
+ # Personal loan
36
+ personal_loan_options = ['yes', 'no']
37
+ personal_loan = st.checkbox('Punya Pinjaman Pribadi?', personal_loan_options)
38
+
39
+ # Contact method
40
+ contact_options = ['cellular', 'telephone', 'unknown']
41
+ contact = st.selectbox('Metode Kontak', contact_options)
42
+
43
+ # Duration
44
+ duration = st.slider('Durasi Kontak Terakhir (detik)', 0, 3600, 1800)
45
+
46
+ # Campaign
47
+ campaign = st.slider('Jumlah Upaya Kontak Selama Campaign', 1, 30, 10)
48
+
49
+ # Pdays
50
+ pdays = st.slider('Jumlah Hari Terakhir Dihubungi (Jika -1, belum pernah)', -1, 20, 10)
51
+
52
+ # Previous
53
+ previous = st.slider('Jumlah Upaya Kontak Sebelum Campaign', 0, 30, 5)
54
+
55
+ # Poutcome
56
+ poutcome_options = ['success', 'failure', 'unknown', 'other']
57
+ poutcome = st.selectbox('Hasil Campaign Sebelumnya', poutcome_options)
58
+
59
+ submit_button = st.form_submit_button('Prediksi')
60
+
61
+
62
+ input_data = pd.DataFrame({
63
+ 'job': [job],
64
+ 'marital': [marital_status],
65
+ 'education': [education],
66
+ 'balance': [balance],
67
+ 'housing': [housing_loan],
68
+ 'loan': [personal_loan],
69
+ 'contact': [contact],
70
+ 'duration': [duration],
71
+ 'campaign': [campaign],
72
+ 'pdays': [pdays],
73
+ 'previous': [previous],
74
+ 'poutcome': [poutcome]
75
+ })
76
+
77
+ data_input = pd.DataFrame(input_data)
78
+ st.dataframe(data_input)
79
+
80
+ if submit_button:
81
+ num_features = ['balance', 'duration', 'campaign', 'pdays', 'previous']
82
+ cat_features = ['job', 'marital', 'contact', 'poutcome', 'housing', 'loan']
83
+ cat_ordinal_feature = ['education']
84
+
85
+ y_pred = best_model_xgb.predict(data_input)
86
+ st.write('Klasifikasi: ', y_pred)
87
+
88
+ if __name__ == '__main__':
89
+ run()
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ seaborn
4
+ matplotlib
5
+ numpy
6
+ scikit-learn==1.4.2
7
+ Pillow
8
+ plotly