开发思路 该脚本将包含以下功能:

  1. 模拟生成包含用户购买、浏览、加购等行为的电商数据。
  2. 进行数据预处理和用户行为特征工程。
  3. 使用K-Means聚类算法对用户进行细分。
  4. 分析并可视化各个用户群体的特征。
  5. 生成一份包含分析过程、用户群体画像和运营建议的综合报告。

import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings("ignore")

# --- 配置 ---
NUM_USERS = 2000
NUM_PRODUCTS = 500
REPORT_PREFIX = '电商用户行为分析报告'
RANDOM_SEED = 42

# --- 数据生成 ---

def generate_sample_user_behavior_data(n_users, n_products):
    """生成模拟的用户行为数据"""
    print("--- 正在生成模拟用户行为数据 ---")
    np.random.seed(RANDOM_SEED)
    
    data = []
    
    # 模拟用户基础信息
    user_ids = [f'user_{i}' for i in range(1, n_users + 1)]
    user_info = []
    for user_id in user_ids:
        age_group = np.random.choice(['18-25', '26-35', '36-45', '46-55', '55+'], p=[0.2, 0.3, 0.25, 0.15, 0.1])
        gender = np.random.choice(['Male', 'Female'], p=[0.5, 0.5])
        location = np.random.choice(['Tier_1', 'Tier_2', 'Tier_3'], p=[0.3, 0.4, 0.3])
        user_info.append({'user_id': user_id, 'age_group': age_group, 'gender': gender, 'location': location})
    df_users = pd.DataFrame(user_info)

    # 模拟用户行为 (浏览、加购、购买)
    # 简化模型:每个用户有不同数量的行为记录
    for user_id in user_ids:
        user_age_group = df_users[df_users['user_id'] == user_id]['age_group'].iloc[0]
        
        # 假设用户有10-100次行为记录
        n_actions = np.random.randint(10, 101)
        
        for _ in range(n_actions):
            product_id = f'prod_{np.random.randint(1, n_products + 1)}'
            action_type = np.random.choice(['view', 'cart', 'purchase'], p=[0.6, 0.3, 0.1])
            timestamp = datetime.now() - timedelta(days=np.random.randint(0, 365), seconds=np.random.randint(0, 86400))
            # 简化:每次行为的金额都随机生成,实际中应关联商品
            amount = np.random.lognormal(6, 1.2) if action_type == 'purchase' else 0.0
            
            data.append({
                'user_id': user_id,
                'product_id': product_id,
                'action_type': action_type,
                'timestamp': timestamp,
                'amount': round(amount, 2)
            })
            
    df_actions = pd.DataFrame(data)
    
    # --- 用户行为特征工程 ---
    print("正在进行用户行为特征工程...")
    
    # 1. 基础统计特征
    user_stats = df_actions.groupby('user_id').agg(
        total_actions=('action_type', 'count'),
        total_purchases=('amount', lambda x: (x > 0).sum()),
        total_spent=('amount', 'sum'),
        avg_action_amount=('amount', lambda x: x.sum() / (x > 0).sum() if (x > 0).sum() > 0 else 0),
        first_action_date=('timestamp', 'min'),
        last_action_date=('timestamp', 'max')
    ).reset_index()
    
    # 2. 衍生特征
    user_stats['tenure_days'] = (user_stats['last_action_date'] - user_stats['first_action_date']).dt.days + 1
    user_stats['purchase_freq'] = user_stats['total_purchases'] / user_stats['tenure_days'] # 日均购买次数
    user_stats['activity_freq'] = user_stats['total_actions'] / user_stats['tenure_days'] # 日均活动次数
    user_stats['avg_order_value'] = user_stats['total_spent'] / user_stats['total_purchases'].replace(0, 1) # 避免除以零
    user_stats['cart_to_purchase_rate'] = user_stats['total_purchases'] / (df_actions[(df_actions['user_id'].isin(user_stats['user_id'])) & (df_actions['action_type'] == 'cart')].groupby('user_id').size().reindex(user_stats['user_id'], fill_value=0) + 1) # +1 避免除以零

    # 3. 最近活跃度 (Recency)
    user_stats['recency_days'] = (datetime.now() - user_stats['last_action_date']).dt.days
    
    # 合并用户基础信息
    df_final = user_stats.merge(df_users, on='user_id', how='left')
    
    csv_filename = f'{REPORT_PREFIX}_用户行为特征数据.csv'
    df_final.to_csv(csv_filename, index=False, encoding='utf-8-sig')
    print(f"用户行为特征数据已生成并保存至: {csv_filename}")
    return df_final

# --- 数据预处理 ---

def preprocess_data(df):
    """数据预处理"""
    print("\n--- 正在进行数据预处理 ---")
    df_processed = df.copy()
    
    # 1. 编码分类变量
    le_age = LabelEncoder()
    le_gender = LabelEncoder()
    le_location = LabelEncoder()
    
    df_processed['age_group_encoded'] = le_age.fit_transform(df_processed['age_group'])
    df_processed['gender_encoded'] = le_gender.fit_transform(df_processed['gender'])
    df_processed['location_encoded'] = le_location.fit_transform(df_processed['location'])
    
    # 2. 选择用于聚类的数值特征列
    # 选择能体现用户价值和行为模式的特征
    feature_columns = [
        'total_actions', 'total_purchases', 'total_spent', 'avg_action_amount',
        'tenure_days', 'purchase_freq', 'activity_freq', 'avg_order_value',
        'cart_to_purchase_rate', 'recency_days'
        # 注意:这里没有包含基础画像特征(age, gender, location),因为聚类主要关注行为模式。
        # 如果需要结合画像细分,可以加入编码后的特征。
    ]
    
    X = df_processed[feature_columns]
    
    # 3. 处理缺失值 (虽然在这个模拟数据中不太可能有缺失,但这是好习惯)
    X = X.fillna(0)
    
    # 4. 特征标准化 (对K-Means至关重要)
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    X_scaled_df = pd.DataFrame(X_scaled, columns=feature_columns)
    
    print(f"预处理完成。特征矩阵形状: {X_scaled_df.shape}")
    return X_scaled_df, scaler, feature_columns

# --- 用户聚类分析 ---

def perform_user_segmentation(X_scaled, max_clusters=10):
    """执行用户聚类分析"""
    print("\n--- 正在执行用户聚类分析 ---")
    
    # 1. 确定最优聚类数 K (肘部法则和轮廓系数)
    print("寻找最优聚类数 K...")
    inertias = []
    silhouette_scores = []
    K_range = range(2, max_clusters+1)
    
    for k in K_range:
        kmeans = KMeans(n_clusters=k, random_state=RANDOM_SEED, n_init=10)
        kmeans.fit(X_scaled)
        inertias.append(kmeans.inertia_)
        score = silhouette_score(X_scaled, kmeans.labels_)
        silhouette_scores.append(score)
        print(f"  K={k}, Inertia={kmeans.inertia_:.2f}, Silhouette Score={score:.3f}")

    # 绘制肘部法则和轮廓系数图
    fig, ax1 = plt.subplots(figsize=(10, 6))

    color = 'tab:blue'
    ax1.set_xlabel('聚类数 K')
    ax1.set_ylabel('簇内平方和 (Inertia)', color=color)
    ax1.plot(K_range, inertias, marker='o', color=color, label='Inertia')
    ax1.tick_params(axis='y', labelcolor=color)

    ax2 = ax1.twinx()  
    color = 'tab:red'
    ax2.set_ylabel('轮廓系数 (Silhouette Score)', color=color)  
    ax2.plot(K_range, silhouette_scores, marker='s', color=color, label='Silhouette Score')
    ax2.tick_params(axis='y', labelcolor=color)
    
    fig.tight_layout() 
    plt.title('肘部法则 & 轮廓系数 vs 聚类数 K')
    plt.xticks(K_range)
    plt.grid(True)
    # 将图例放在图表下方
    lines, labels = ax1.get_legend_handles_labels()
    lines2, labels2 = ax2.get_legend_handles_labels()
    ax2.legend(lines + lines2, labels + labels2, loc='upper center', bbox_to_anchor=(0.5, -0.15), ncol=2)
    
    k_plot_path = f'{REPORT_PREFIX}_最优K值分析.png'
    plt.savefig(k_plot_path, bbox_inches='tight')
    plt.close()
    print(f"最优K值分析图表已保存至: {k_plot_path}")
    
    # 选择最优K (这里我们选择轮廓系数最高的K,也可以结合肘部法则)
    optimal_k = K_range[np.argmax(silhouette_scores)]
    print(f"选择最优聚类数 K = {optimal_k}")
    
    # 2. 使用最优K进行聚类
    print(f"使用 K={optimal_k} 进行最终聚类...")
    kmeans_final = KMeans(n_clusters=optimal_k, random_state=RANDOM_SEED, n_init=10)
    cluster_labels = kmeans_final.fit_predict(X_scaled)
    
    return cluster_labels, optimal_k, kmeans_final

# --- 聚类结果分析与可视化 ---

def analyze_and_visualize_clusters(df, X_scaled_df, cluster_labels, feature_columns, optimal_k):
    """分析和可视化聚类结果"""
    print("\n--- 正在分析和可视化聚类结果 ---")
    
    df['cluster'] = cluster_labels
    
    # 1. 各聚类的基本统计信息
    cluster_summary = df.groupby('cluster').agg(
        user_count=('user_id', 'count'),
        mean_total_spent=('total_spent', 'mean'),
        mean_total_purchases=('total_purchases', 'mean'),
        mean_activity_freq=('activity_freq', 'mean'),
        mean_recency_days=('recency_days', 'mean'),
        mean_tenure_days=('tenure_days', 'mean')
    ).round(2)
    cluster_summary['pct_of_users'] = (cluster_summary['user_count'] / len(df) * 100).round(2)
    
    print("各用户群体基本统计摘要:")
    print(cluster_summary.to_string())
    
    summary_csv_path = f'{REPORT_PREFIX}_用户群体摘要.csv'
    cluster_summary.to_csv(summary_csv_path, encoding='utf-8-sig')
    print(f"用户群体摘要已保存至: {summary_csv_path}")

    # 2. 可视化:使用PCA降维后绘制散点图
    print("生成PCA降维可视化图...")
    pca = PCA(n_components=2, random_state=RANDOM_SEED)
    X_pca = pca.fit_transform(X_scaled_df)
    
    plt.figure(figsize=(10, 8))
    scatter = plt.scatter(X_pca[:, 0], X_pca[:, 1], c=cluster_labels, cmap='viridis', alpha=0.6)
    plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.1%} variance)')
    plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.1%} variance)')
    plt.title('用户群体聚类 (PCA降维可视化)')
    plt.colorbar(scatter, label='Cluster')
    # 添加聚类中心 (在PCA空间中)
    centers_pca = pca.transform(kmeans.cluster_centers_)
    plt.scatter(centers_pca[:, 0], centers_pca[:, 1], c='red', marker='x', s=200, linewidths=3, label='Centroids')
    plt.legend()
    pca_plot_path = f'{REPORT_PREFIX}_用户群体PCA可视化.png'
    plt.savefig(pca_plot_path)
    plt.close()
    print(f"PCA可视化图表已保存至: {pca_plot_path}")

    # 3. 可视化:各群体关键特征雷达图 (每个群体一个图)
    print("生成各用户群体特征雷达图...")
    # 计算每个群体在各特征上的平均Z-score (标准化后的值)
    cluster_profiles = X_scaled_df.copy()
    cluster_profiles['cluster'] = cluster_labels
    cluster_averages = cluster_profiles.groupby('cluster').mean()
    
    # 为雷达图准备数据
    num_vars = len(feature_columns)
    angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
    angles += angles[:1] # 闭合图形
    
    fig, axes = plt.subplots(2, (optimal_k + 1) // 2, figsize=(5 * (optimal_k + 1) // 2, 10), subplot_kw=dict(polar=True))
    if optimal_k == 2:
         axes = axes.reshape(1, -1) # 如果只有2个簇,axes是一维的
    fig.suptitle('用户群体特征雷达图', fontsize=16)
    
    for i in range(optimal_k):
        row = i // axes.shape[1]
        col = i % axes.shape[1]
        ax = axes[row, col] if axes.ndim > 1 else axes[col]
        
        values = cluster_averages.iloc[i].tolist()
        values += values[:1]
        ax.plot(angles, values, linewidth=2, label=f'Cluster {i}')
        ax.fill(angles, values, alpha=0.25)
        ax.set_xticks(angles[:-1])
        ax.set_xticklabels(feature_columns, fontsize=8)
        ax.set_ylim([-3, 3]) # 标准化后的值通常在这个范围
        ax.set_title(f'群体 {i}', fontsize=12)
        ax.yaxis.grid(True)
        
    # 隐藏多余的子图 (如果簇数是奇数)
    if optimal_k % 2 != 0 and axes.ndim > 1:
        fig.delaxes(axes[1, -1])

    plt.tight_layout(rect=[0, 0.03, 1, 0.95])
    radar_plot_path = f'{REPORT_PREFIX}_用户群体雷达图.png'
    plt.savefig(radar_plot_path)
    plt.close()
    print(f"用户群体雷达图已保存至: {radar_plot_path}")
    
    return cluster_summary

# --- 报告生成 ---

def generate_user_segmentation_report(cluster_summary, optimal_k, k_plot_path, pca_plot_path, radar_plot_path):
    """生成最终的用户行为分析与细分报告"""
    print("\n--- 正在生成用户行为分析与细分报告 ---")
    from datetime import datetime
    report_filename = f"{REPORT_PREFIX}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
    
    with open(report_filename, 'w', encoding='utf-8') as f:
        f.write("=" * 50 + "\n")
        f.write("        电商平台用户行为分析与细分报告\n")
        f.write(f"        生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        f.write("=" * 50 + "\n\n")

        f.write("--- 1. 项目概述 ---\n")
        f.write("本项目旨在通过对电商平台用户行为数据的深入分析,将用户划分为不同的群体。\n")
        f.write("目标是理解不同用户群体的行为特征,为精细化运营、个性化推荐和精准营销提供数据支持。\n\n")

        f.write("--- 2. 数据概览 ---\n")
        f.write("数据来源: 模拟生成的电商平台用户行为数据。\n")
        f.write("数据规模: 2000 名用户,500 种商品。\n")
        f.write("关键行为: 浏览 (view), 加购 (cart), 购买 (purchase)。\n")
        f.write("关键字段: 用户ID, 商品ID, 行为类型, 时间戳, 金额等。\n")
        f.write("原始特征数据已保存为 CSV 文件。\n\n")

        f.write("--- 3. 用户行为特征工程 ---\n")
        f.write("从原始行为日志中提取了能反映用户价值和行为模式的关键指标:\n")
        f.write("- 总行为次数 (total_actions)\n")
        f.write("- 总购买次数 (total_purchases)\n")
        f.write("- 总消费金额 (total_spent)\n")
        f.write("- 平均行为金额 (avg_action_amount)\n")
        f.write("- 用户生命周期 (tenure_days)\n")
        f.write("- 购买频率 (purchase_freq)\n")
        f.write("- 活动频率 (activity_freq)\n")
        f.write("- 平均订单价值 (avg_order_value)\n")
        f.write("- 加购转化率 (cart_to_purchase_rate)\n")
        f.write("- 最近活跃度 (recency_days)\n\n")

        f.write("--- 4. 用户群体细分 ---\n")
        f.write(f"采用 K-Means 聚类算法,通过肘部法则和轮廓系数分析,确定最优聚类数 K = {optimal_k}。\n")
        f.write("分析过程图表已生成,包括:\n")
        f.write(f"- 最优K值选择分析图: {k_plot_path}\n")
        f.write(f"- PCA降维可视化图: {pca_plot_path}\n")
        f.write(f"- 用户群体特征雷达图: {radar_plot_path}\n\n")
        
        f.write("--- 5. 用户群体画像 ---\n")
        f.write("根据聚类结果,用户被划分为以下群体,各群体特征摘要如下:\n")
        f.write(cluster_summary.to_string())
        f.write("\n\n基于以上数据,可以对每个群体进行命名和描述:\n")
        f.write("(命名需结合雷达图等可视化信息进行人工解读)\n")
        f.write("例如:\n")
        f.write("- 高价值客户: 高消费金额、高购买频率、低近期活跃度可能表示忠诚老客户。\n")
        f.write("- 潜力客户: 中等活动频率、中等消费、高近期活跃度。\n")
        f.write("- 新兴客户: 短生命周期、低活动频率、但高近期活跃度。\n")
        f.write("- 流失风险客户: 低活动频率、低购买频率、高近期活跃度。\n")
        f.write("- 低价值客户: 各项指标均较低。\n\n")

        f.write("--- 6. 运营策略与建议 ---\n")
        f.write("1. 精准营销:\n")
        f.write("   - 对'高价值客户'提供VIP服务、专属优惠,提高忠诚度。\n")
        f.write("   - 对'潜力客户'推送个性化商品推荐,刺激消费。\n")
        f.write("   - 对'新兴客户'提供新人礼包,引导完成首单。\n")
        f.write("   - 对'流失风险客户'发送召回优惠券或进行用户关怀。\n")
        f.write("2. 个性化推荐: 根据不同群体的偏好调整推荐算法。\n")
        f.write("3. 产品优化: 分析各群体热门商品,优化商品结构。\n")
        f.write("4. 用户体验: 针对不同群体优化App或网站的用户界面和功能。\n")
        f.write("5. 模型迭代: 定期更新用户行为数据和群体划分,以适应市场变化。\n\n")

        f.write("=" * 50 + "\n")
        f.write("                    报告结束\n")
        f.write("=" * 50 + "\n")

    print(f"用户行为分析与细分报告已生成: {report_filename}")

# --- 主函数 ---

def main():
    """主函数"""
    # 1. 生成数据
    df_user_features = generate_sample_user_behavior_data(NUM_USERS, NUM_PRODUCTS)
    
    # 2. 数据预处理
    X_scaled_df, scaler, feature_cols = preprocess_data(df_user_features)
    
    # 3. 用户聚类分析
    cluster_labels, optimal_k, kmeans = perform_user_segmentation(X_scaled_df)
    
    # 4. 分析和可视化聚类结果
    cluster_summary = analyze_and_visualize_clusters(df_user_features, X_scaled_df, cluster_labels, feature_cols, optimal_k)
    
    # 5. 生成报告
    generate_user_segmentation_report(cluster_summary, optimal_k, f'{REPORT_PREFIX}_最优K值分析.png', f'{REPORT_PREFIX}_用户群体PCA可视化.png', f'{REPORT_PREFIX}_用户群体雷达图.png')
    
    print("\n用户行为分析与细分流程完成。")

if __name__ == "__main__":
    main()