maitrang04's picture
Upload 48 files
0649d3e verified
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.cluster import KMeans
from backend.config.setting import (
PRE_TELCO_CHURN_CSV,
PRE_TEST_CUSTOMER_CSV,
)
df1 = pd.read_csv(PRE_TELCO_CHURN_CSV)
df2 = pd.read_csv(PRE_TEST_CUSTOMER_CSV)
df = pd.concat([df1, df2], ignore_index=True)
# Danh sách đầy đủ các feature bạn yêu cầu
features_to_use = [
'Customer ID',
'Age',
'Avg Monthly GB Download',
'Churn Score',
'Gender',
'Monthly Charge',
'CLTV',
'Contract',
'Streaming Movies',
'Streaming Music',
'Streaming TV',
'Satisfaction Score',
'Tenure in Months'
]
# Chỉ giữ lại các cột có trong file
existing_cols = [col for col in features_to_use if col in df.columns]
df_final = df[existing_cols].copy()
# Kiểm tra xem có đủ cột quan trọng không
if 'Customer ID' not in df_final.columns:
print(" Cảnh báo: Không tìm thấy cột Customer ID. Code vẫn chạy nhưng kết quả sẽ không có ID.")
# ==========================================
# 2. TIỀN XỬ LÝ (PRE-PROCESSING)
# ==========================================
# Tạo một bản sao để train model (không làm hỏng data gốc)
X = df_final.copy()
# Bỏ cột ID ra khỏi dữ liệu training (vì ID không có ý nghĩa phân cụm)
if 'Customer ID' in X.columns:
X = X.drop(columns=['Customer ID'])
# --- 2.1 Xử lý dữ liệu dạng chữ (Encoding) ---
# Xử lý Gender: Male/Female -> 0/1
le = LabelEncoder()
if 'Gender' in X.columns:
X['Gender'] = le.fit_transform(X['Gender'].astype(str))
# Xử lý Contract: Chuyển thành số theo thứ tự cam kết
contract_map = {'Month-to-month': 0, 'One year': 1, 'Two year': 2}
if 'Contract' in X.columns:
# Nếu dữ liệu lạ không khớp map, gán là 0
X['Contract'] = X['Contract'].map(contract_map).fillna(0)
# Xử lý các cột Streaming: Yes -> 1, No -> 0
streaming_cols = ['Streaming Movies', 'Streaming Music', 'Streaming TV']
for col in streaming_cols:
if col in X.columns:
# Xử lý cả trường hợp 'No internet service' -> coi là 0
X[col] = X[col].apply(lambda x: 1 if str(x).strip() == 'Yes' else 0)
# --- 2.2 Xử lý dữ liệu trống (Missing Values) ---
# Điền giá trị trung bình vào các ô trống (để tránh lỗi)
X = X.fillna(X.mean())
# --- 2.3 Chuẩn hóa dữ liệu (Scaling) ---
# Bước này CỰC KỲ QUAN TRỌNG khi dùng nhiều feature khác đơn vị (Tuổi, Tiền, GB...)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# ==========================================
# 3. PHÂN CỤM (CLUSTERING)
# ==========================================
print(" Đang tiến hành phân cụm K-Means với 3 nhóm...")
# Sử dụng K-Means với k=3
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
clusters = kmeans.fit_predict(X_scaled)
# Gán nhãn cụm (0, 1, 2) tạm thời vào dataframe
df_final['Cluster_Temp'] = clusters
# ==========================================
# 4. ĐỊNH DANH NHÓM A, B, C (RANKING)
# ==========================================
# Logic: Nhóm nào có CLTV (Giá trị vòng đời) cao nhất sẽ là A (VIP)
# Nếu không có CLTV, dùng Monthly Charge
ranking_metric = 'CLTV' if 'CLTV' in df_final.columns else 'Monthly Charge'
# Tính giá trị trung bình của metric xếp hạng cho từng cụm
cluster_stats = df_final.groupby('Cluster_Temp')[ranking_metric].mean().sort_values(ascending=False)
print("\n Thống kê trung bình nhóm (Dựa trên CLTV):")
print(cluster_stats)
# Tạo map: Cao nhất -> A, Nhì -> B, Thấp -> C
labels_map = {}
rank_names = ['A', 'B', 'C'] # A là xịn nhất
for i, cluster_idx in enumerate(cluster_stats.index):
labels_map[cluster_idx] = rank_names[i]
# Áp dụng map để tạo cột Segment cuối cùng
df_final['Segment'] = df_final['Cluster_Temp'].map(labels_map)
# ==========================================
# 5. XUẤT FILE KẾT QUẢ
# ==========================================
# Bỏ cột Cluster_Temp thừa đi
output_df = df_final.drop(columns=['Cluster_Temp'])
filename = "telco_customer_segmented_full_features.csv"
output_df.to_csv(filename, index=False)
print(f"\n THÀNH CÔNG! File kết quả đã lưu tại: {filename}")
print("-" * 50)
print("Mẫu dữ liệu 5 dòng đầu tiên:")
print(output_df[['Customer ID', 'Segment', 'CLTV', 'Churn Score', 'Monthly Charge']].head())
# In ra đặc điểm trung bình của từng nhóm để bạn dễ hiểu Insight
print("\n ĐẶC ĐIỂM TRUNG BÌNH CỦA 3 NHÓM KHÁCH HÀNG:")
summary = output_df.groupby('Segment')[['CLTV', 'Monthly Charge', 'Churn Score', 'Avg Monthly GB Download']].mean()
print(summary)