422 lines
41 KiB
Plaintext
422 lines
41 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"metadata": {},
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## 多维高斯分布\n",
|
||
"异常率高达30%\n",
|
||
"\n"
|
||
],
|
||
"id": "d579b46fd796cfd8"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"id": "initial_id",
|
||
"metadata": {
|
||
"collapsed": true,
|
||
"ExecuteTime": {
|
||
"end_time": "2025-06-27T05:32:55.492952Z",
|
||
"start_time": "2025-06-27T05:32:54.368572Z"
|
||
}
|
||
},
|
||
"source": [
|
||
"import numpy as np\n",
|
||
"import pandas as pd\n",
|
||
"from sklearn.covariance import MinCovDet\n",
|
||
"from scipy.stats import chi2\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"import seaborn as sns\n",
|
||
"\n",
|
||
"plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体显示中文\n",
|
||
"plt.rcParams['axes.unicode_minus'] = False\n",
|
||
"\n",
|
||
"# 设置 seaborn 风格(避免因旧版 cm.register_cmap 报错)\n",
|
||
"sns.set_theme(style=\"whitegrid\")\n",
|
||
"\n",
|
||
"# 读取 Excel 数据\n",
|
||
"file_path = r\"D:\\Idea Project\\F6+宜搭+其它(1)\\new\\文件输入\\孤立森林数据1 2025-06-27 11-42-26.xlsx\"\n",
|
||
"df = pd.read_excel(file_path, sheet_name=\"孤立森林数据1\")\n",
|
||
"\n",
|
||
"\n",
|
||
"columns_to_keep = [\n",
|
||
" '销售金额(除税)',\n",
|
||
" '销售内容(销售量)',\n",
|
||
" '会员卡ID(会员数量)',\n",
|
||
" '客单价',\n",
|
||
" '客户ID(客户数量)'\n",
|
||
"]\n",
|
||
"df = df[columns_to_keep]\n",
|
||
"\n",
|
||
"\n",
|
||
"# 使用稳健协方差估计器(MCD)计算 Mahalanobis 距离\n",
|
||
"mcd = MinCovDet().fit(df)\n",
|
||
"mahal_dist = mcd.mahalanobis(df)\n",
|
||
"\n",
|
||
"# 添加到 DataFrame\n",
|
||
"df['mahal_dist'] = mahal_dist\n",
|
||
"\n",
|
||
"# 设置阈值:基于卡方分布(自由度为特征数)\n",
|
||
"threshold = chi2.ppf(0.999, df.shape[1])\n",
|
||
"df['anomaly'] = df['mahal_dist'] > threshold\n",
|
||
"\n",
|
||
"# 输出部分结果查看\n",
|
||
"print(df.head(10))\n",
|
||
"\n",
|
||
"# 可视化 Mahalanobis Distance 分布\n",
|
||
" # 正常显示负号\n",
|
||
"plt.figure(figsize=(10, 6))\n",
|
||
"sns.histplot(df['mahal_dist'], bins=30, kde=True, color='skyblue', stat='density')\n",
|
||
"\n",
|
||
"# 绘制阈值线\n",
|
||
"# plt.axvline(threshold, color='r', linestyle='--', label=f'阈值 (99%) = {threshold:.2f}')\n",
|
||
"# plt.title('Mahalanobis Distance 分布')\n",
|
||
"# plt.xlabel('Mahalanobis Distance')\n",
|
||
"# plt.ylabel('密度')\n",
|
||
"# plt.legend()\n",
|
||
"# plt.tight_layout()\n",
|
||
"# plt.show()\n",
|
||
"\n",
|
||
"# 导出结果\n",
|
||
"output_path = r\"D:\\Idea Project\\F6+宜搭+其它(1)\\new\\文件输出\\门店经营异常检测结果.xlsx\"\n",
|
||
"df.to_excel(output_path, index=False)\n",
|
||
"print(f\"✅ 异常检测结果已保存至: {output_path}\")\n",
|
||
"\n",
|
||
"# 打印异常记录\n",
|
||
"anomalies = df[df['anomaly'] == True]\n",
|
||
"print(\"\\n🚨 异常记录如下:\")\n",
|
||
"print(anomalies)"
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
" 销售金额(除税) 销售内容(销售量) 会员卡ID(会员数量) 客单价 客户ID(客户数量) mahal_dist \\\n",
|
||
"0 59987.610620 171 0 350.804740 171 6.061404 \n",
|
||
"1 946.017700 41 0 23.073602 41 21.575012 \n",
|
||
"2 24889.380532 120 0 207.411504 120 0.881923 \n",
|
||
"3 76138.053105 371 0 205.223863 371 2.263268 \n",
|
||
"4 105610.884947 450 1 234.690855 450 24.857742 \n",
|
||
"5 50076.991149 214 0 234.004632 214 0.434116 \n",
|
||
"6 58241.592917 281 0 207.265455 281 0.530889 \n",
|
||
"7 38558.530968 299 0 128.958298 299 3.750139 \n",
|
||
"8 103886.725658 272 1 381.936491 272 33.840041 \n",
|
||
"9 39316.814163 304 0 129.331626 304 3.949294 \n",
|
||
"\n",
|
||
" anomaly \n",
|
||
"0 False \n",
|
||
"1 False \n",
|
||
"2 False \n",
|
||
"3 False \n",
|
||
"4 True \n",
|
||
"5 False \n",
|
||
"6 False \n",
|
||
"7 False \n",
|
||
"8 True \n",
|
||
"9 False \n",
|
||
"✅ 异常检测结果已保存至: D:\\Idea Project\\F6+宜搭+其它(1)\\new\\文件输出\\门店经营异常检测结果.xlsx\n",
|
||
"\n",
|
||
"🚨 异常记录如下:\n",
|
||
" 销售金额(除税) 销售内容(销售量) 会员卡ID(会员数量) 客单价 客户ID(客户数量) \\\n",
|
||
"4 105610.884947 450 1 234.690855 450 \n",
|
||
"8 103886.725658 272 1 381.936491 272 \n",
|
||
"13 258112.743358 765 0 337.402279 765 \n",
|
||
"15 148439.823009 561 2 264.598615 561 \n",
|
||
"16 65226.548667 303 2 215.269138 303 \n",
|
||
"... ... ... ... ... ... \n",
|
||
"3524 29609.168143 207 27 143.039460 207 \n",
|
||
"3525 31389.477879 149 16 210.667637 149 \n",
|
||
"3526 52441.654860 326 12 160.863972 326 \n",
|
||
"3527 36573.336284 118 5 309.943528 118 \n",
|
||
"3528 2111.504424 18 2 117.305801 18 \n",
|
||
"\n",
|
||
" mahal_dist anomaly \n",
|
||
"4 24.857742 True \n",
|
||
"8 33.840041 True \n",
|
||
"13 232.095636 True \n",
|
||
"15 104.399472 True \n",
|
||
"16 73.634968 True \n",
|
||
"... ... ... \n",
|
||
"3524 14058.748066 True \n",
|
||
"3525 4933.658230 True \n",
|
||
"3526 2753.222833 True \n",
|
||
"3527 484.611436 True \n",
|
||
"3528 82.198933 True \n",
|
||
"\n",
|
||
"[1130 rows x 7 columns]\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<Figure size 1000x600 with 1 Axes>"
|
||
],
|
||
"image/png": "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SkqKZs+erY4dO2r37t36xS9+ofnz52v06NGSpB9//FFz5szRV199pdjYWF122WWaNWuWde+bJL377rtaunSp9u3bp86dO2v69Ol+RyM0VR8AAAAAcDLZHugAAAAAAKGxdcklAAAAACB0BDoAAAAAiFAEOgAAAACIUAQ6AAAAAIhQBDoAAAAAiFAEOgAAAACIUAQ6+PF6vVq8eLGGDBmivn37asKECdq1a5fdwzpl5efnq2vXrrU+Vq1aJUnKycnR2LFj1bdvXw0fPlyvvPKK3/ODqVc4+kClZ599VjfffLPfNafUqKE+TmeB6vbAAw/U+r4bPny49Th1a3qHDx/W7NmzNXToUCUnJ2vMmDHasGGD9fi6des0evRo9enTR5dddplWr17t93yPx6M5c+YoLS1N/fr107Rp03Tw4EG/Nk3Rx+mkoZrddttttb7Pan4vUjN7/Pjjj5o+fboGDhyofv36aeLEidqxY4f1OD/XIpAJ1PD000+bAwYMMD///HMzJyfHvP32282RI0eaHo/H7qGdkr744guzV69eZn5+vllQUGB9FBcXmwcPHjQHDBhgzpo1y9y+fbv51ltvmb169TLfeust6/kN1SscfaDSa6+9Znbr1s0cO3asdc0pNQqmj9NVoLqZpmlee+215sKFC/2+73788UfrcerW9G677Tbz8ssvN9evX29+99135pw5c8zevXubO3bsMLdv32726tXLXLhwobl9+3bzhRdeMHv06GH+3//9n/X8mTNnmiNGjDDXr19vfv3112Z6erp50003WY83VR+nk/pqZpqmmZaWZq5cudLv++zQoUPW86mZPX7zm9+Y1113nfn111+b27dvN++++25z8ODBZlFRET/XIhSBDhaPx2P269fP/Mtf/mJdO3LkiNm7d2/zgw8+sHFkp67nnnvOvOKKKwI+9swzz5iDBw82y8rKrGtPPvmkOXLkSNM0g6tXOPo43e3bt8+88847zb59+5qXXXaZXzBwSo0a6uN0VF/dvF6v2bdvX3PNmjUBn0vdmt7OnTvNLl26mBs2bLCueb1ec8SIEeZTTz1lPvjgg+a1117r95ypU6eat99+u2malfXu1q2b+cUXX1iPf/fdd2aXLl3MjRs3mqZpNkkfp5OGanbgwAGzS5cu5r///e+Az6dm9jh8+LA5depUc8uWLda1nJwcs0uXLubX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detW63F+rkUewzRPw0M4AAAAAOAUcPotHgYAAACAUwSBDgAAAAAiFIEOAAAAACIUgQ4AAAAAIhSBDgAAAAAiFIEOAAAAACIUgQ4AAAAAIhSBDgAA1IsjawHAuQh0AACEycyZMzV8+PAT7iczM1Ndu3ZVZmbmCfd188036+abb7Z+P3z4cM2cOTPo53/66aeaMWPGCY8DAHByRNk9AAAA0HSWLFmiFi1aBN1+xYoVJ28wAIATRqADAOA00qNHD7uHAAAII5ZcAgBOO8OHD9eSJUv0yCOPaMCAAerXr5+mTZumY8eO6bnnntPQoUN14YUX6u6779ahQ4ckSSUlJXryySc1cuRIXXDBBUpOTtZtt92mnJycWv2vWrVKl156qXr16qUrr7xSX375pd/j69ev1x133KGUlBRdcMEFGj58uJ5++ml5vd4T+rr27Nmj3//+97rwwgs1aNAgLV++PODXXnPJ5Ycffqgrr7xSvXv31sCBA3XvvfcqPz9fUuVyzaysLGVlZYVtCSgAILwIdACA09JLL72kvXv3atGiRZo0aZI+/PBDXXPNNfr73/+uefPmaerUqfr000+1ePFiSdJ9992nt99+WxMnTtRLL72kWbNmadu2bZo2bZrfpiF79+7Vc889p//+7//W008/LcMwNHnyZP3444+SpNzcXN16661KSEjQokWLtGzZMvXv319LlizRxx9/HPLXU1RUpLFjx2rr1q2aN2+eHnzwQb355pvatGlTnc/Jzs7Wfffdp5EjR+r555/XrFmzlJGRoWnTpkmS/vCHP6hHjx7q0aOH/vrXv6pnz54hjw8AcHKw5BIAcFpq0aKFFi1apKioKF100UV65513lJ+frzfffFMtW7aUJH311VfauHGjSktLdezYMT3wwAMaNWqUJCk1NVVHjx7Vo48+qgMHDqht27aSJK/Xqz//+c/q1KmTJCk2Nla33nqr/vnPf+oXv/iFcnNzddFFF+mJJ56Qy1X576qDBg3SZ599pszMTP36178O6et55513tGfPHn344Yfq3LmzJKlPnz765S9/WedzsrOz1axZM02cOFExMTGSpISEBG3evFmmaapz587W/XZ9+/YNaVwAgJOLQAcAOC317t1bUVHVPwbPPPNMxcfHW2FOqgw3W7duVUxMjF588UVJUn5+vr7//nvt3LlTn3/+uSSptLTUek5iYqIV5iSpY8eOkqSffvpJkpSenq709HR5PB59//33ysvLU05OjioqKlRWVhby17NhwwadffbZVpiTpA4dOtQbxFJSUrRo0SJdfvnluvTSS3XxxRdr8ODBuvjii0MeBwCgaRHoAACnpUA7PcbHx9fZ/quvvtIjjzyi7777Ts2bN1e3bt2s9jWXXB7fh2EYkmTdH1dSUqJ58+bpvffeU3l5uTp27Kh+/fopKirqhM57O3LkiBITE2tdb9u2rQ4cOBDwOf369dNzzz2nFStWaPny5Xruued05pln6re//a3fUQcAAOci0AEA0IAffvhBv/vd7zRixAg9++yz+tnPfibDMPSXv/xFX331VaP6evjhh/XJJ5/oqaee0kUXXWQFwLS0tBMaY2JiovLy8mpdP3z4cL3PGzJkiIYMGaLi4mJlZGTolVde0R//+Ef16dNHvXv3PqExAQBOPjZFAQCgAf/617/k8Xg0ceJEnX322dasmy/MNWZmLTs7WwMGDNCIESOsMPevf/1LBw8ePKFdLgcOHKjdu3dr8+bN1rWDBw/qn//8Z53Peeyxx3TNNdfINE3FxcXpkksusQ4R37NnjyRZ9/kBAJyJGToAABrQs2dPRUVF6YknntDtt9+u0tJSrVq1Sl988YWkyh0mg9W7d299/PHHev3119WpUyfl5uZq2bJlMgxDxcXFIY/xqquu0iuvvKLf//73mjJlilq0aKFly5bVGxIHDhyo5cuXa+bMmbryyitVVlamF154QQkJCRo4cKAkqVWrVtq0aZPWrVunHj16qHXr1iGPEQAQfvyzGwAADTjnnHP05JNPKj8/X5MmTdLs2bMlSa+++qoMw9CGDRuC7mvmzJkaMWKEnnrqKd1555168803NWnSJF1//fXatGmTKioqQhpjTEyMXn75ZaWkpOjhhx/W//t//09paWm65JJL6nzOxRdfrAULFmjbtm36/e9/r6lTpyouLk6vvPKKEhISJEk33XSToqOjNWHCBP3tb38LaWwAgJPHME/kDmwAAAAAgG1YcgkAgINVVFQ0eI+eYRhyu91NNCIAgJMwQwcAgIMNHz5c//nPf+ptk5qaqldffbWJRgQAcBICHQAADrZlyxa/g8sDad68uc4///wmGhEAwEkIdAAAAAAQodjlEgAAAAAiFIEOAAAAACIUgQ4AAAAAIhSBDgAAAAAiFIEOAAAAACIUgQ4AAAAAIhSBDgAAAAAiFIEOAAAAACLU/wcfNlSBB5cVqAAAAABJRU5ErkJggg=="
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"execution_count": 11
|
||
},
|
||
{
|
||
"metadata": {},
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## 孤立森林,含马氏距离\n",
|
||
"\n",
|
||
"输出结果包含两者的异常数据及共同异常数据"
|
||
],
|
||
"id": "e48b026b8a293dd2"
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-06-27T06:46:48.684608Z",
|
||
"start_time": "2025-06-27T06:46:45.571499Z"
|
||
}
|
||
},
|
||
"cell_type": "code",
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"import numpy as np\n",
|
||
"from sklearn.covariance import MinCovDet\n",
|
||
"from scipy.stats import chi2\n",
|
||
"from sklearn.preprocessing import StandardScaler, PowerTransformer\n",
|
||
"from sklearn.decomposition import PCA\n",
|
||
"from sklearn.ensemble import IsolationForest\n",
|
||
"from sklearn.neighbors import LocalOutlierFactor\n",
|
||
"import warnings\n",
|
||
"\n",
|
||
"# 读取数据\n",
|
||
"file_path = r\"D:\\Idea Project\\F6+宜搭+其它(1)\\new\\文件输入\\孤立森林数据1 2025-06-27 11-42-26.xlsx\"\n",
|
||
"df = pd.read_excel(file_path)\n",
|
||
"\n",
|
||
"# 数据预处理\n",
|
||
"df['结清时间'] = pd.to_datetime(df['结清时间'])\n",
|
||
"df = df.sort_values(by=['门店ID', '结清时间'])\n",
|
||
"\n",
|
||
"# 所有原始特征\n",
|
||
"original_features = ['销售金额(除税)', '销售内容(销售量)', '会员卡ID(会员数量)', '客户ID(客户数量)']\n",
|
||
"\n",
|
||
"# 初始化结果字典 {sheet_name: DataFrame}\n",
|
||
"results_by_store = {}\n",
|
||
"all_results = []\n",
|
||
"\n",
|
||
"# 特征有效性检查函数\n",
|
||
"def filter_valid_features(group, features, min_unique=2):\n",
|
||
" valid = []\n",
|
||
" for col in features:\n",
|
||
" if group[col].nunique() >= min_unique:\n",
|
||
" valid.append(col)\n",
|
||
" else:\n",
|
||
" print(f\"⚠️ 特征 {col} 在门店 {group['门店名'].iloc[0]} 中唯一值数量为 {group[col].nunique()},被过滤\")\n",
|
||
" return valid\n",
|
||
"\n",
|
||
"# 异常检测函数\n",
|
||
"def detect_anomalies(X_scaled):\n",
|
||
" results = {}\n",
|
||
"\n",
|
||
" with warnings.catch_warnings():\n",
|
||
" warnings.filterwarnings(\"ignore\", message=\"Determinant has increased\", category=RuntimeWarning)\n",
|
||
" mcd = MinCovDet(support_fraction=0.8, random_state=42).fit(X_scaled)\n",
|
||
" mahal_dist = mcd.mahalanobis(X_scaled)\n",
|
||
" threshold_mahal = chi2.ppf(0.999, X_scaled.shape[1])\n",
|
||
" results['Mahalanobis_Anomaly'] = (mahal_dist > threshold_mahal)\n",
|
||
"\n",
|
||
" iso_forest = IsolationForest(contamination='auto', random_state=42)\n",
|
||
" iso_pred = iso_forest.fit_predict(X_scaled)\n",
|
||
" results['Isolation_Forest_Anomaly'] = (iso_pred == -1)\n",
|
||
"\n",
|
||
" lof = LocalOutlierFactor(n_neighbors=min(5, len(X_scaled) - 1))\n",
|
||
" lof_pred = lof.fit_predict(X_scaled)\n",
|
||
" results['LOF_Anomaly'] = (lof_pred == -1)\n",
|
||
"\n",
|
||
" return pd.DataFrame(results)\n",
|
||
"\n",
|
||
"# 主循环处理每个门店\n",
|
||
"for (store_id, store_name), group in df.groupby(['门店ID', '门店名']):\n",
|
||
" print(f\"\\n正在处理门店: {store_name}\")\n",
|
||
"\n",
|
||
" result = group.copy()\n",
|
||
"\n",
|
||
" # 【关键步骤】计算“会员卡使用占比”\n",
|
||
" member_usage_ratio = (group['会员卡ID(会员数量)'] > 0).mean()\n",
|
||
" print(f\"✅ 门店 {store_name} 的会员卡使用占比为 {member_usage_ratio:.1%}\")\n",
|
||
"\n",
|
||
" # 动态决定是否保留“会员卡ID(会员数量)”字段\n",
|
||
" if member_usage_ratio >= 0.2:\n",
|
||
" pt = PowerTransformer(method='yeo-johnson')\n",
|
||
" group['会员数_YJ'] = pt.fit_transform(group[['会员卡ID(会员数量)']])\n",
|
||
" current_features = ['销售金额(除税)', '销售内容(销售量)', '客户ID(客户数量)', '会员数_YJ']\n",
|
||
" else:\n",
|
||
" current_features = ['销售金额(除税)', '销售内容(销售量)', '客户ID(客户数量)']\n",
|
||
"\n",
|
||
" # 自动过滤无效特征\n",
|
||
" valid_features = filter_valid_features(group, current_features, min_unique=2)\n",
|
||
"\n",
|
||
" if len(valid_features) < 2:\n",
|
||
" print(f\"❌ 门店 {store_name} 只剩少于2个有效特征,跳过异常检测\")\n",
|
||
" results_by_store[store_name] = result\n",
|
||
" continue\n",
|
||
"\n",
|
||
" X = group[valid_features]\n",
|
||
" X_scaled = StandardScaler().fit_transform(X)\n",
|
||
"\n",
|
||
" # 使用 PCA 去除共线性\n",
|
||
" pca = PCA(n_components=0.95)\n",
|
||
" X_pca = pca.fit_transform(X_scaled)\n",
|
||
"\n",
|
||
" # 执行多模型检测\n",
|
||
" anomaly_df = detect_anomalies(X_pca)\n",
|
||
"\n",
|
||
" # 合并回原数据\n",
|
||
" result = pd.concat([result.reset_index(drop=True), anomaly_df.reset_index(drop=True)], axis=1)\n",
|
||
"\n",
|
||
" # 存储该门店的结果\n",
|
||
" results_by_store[store_name] = result\n",
|
||
" all_results.append(result)\n",
|
||
"\n",
|
||
"# 合并所有门店结果\n",
|
||
"final_all = pd.concat(all_results, ignore_index=True)\n",
|
||
"\n",
|
||
"# 写入 Excel(多个 sheet)\n",
|
||
"output_file = \"门店异常检测结果_多模型.xlsx\"\n",
|
||
"\n",
|
||
"with pd.ExcelWriter(output_file, engine='xlsxwriter') as writer:\n",
|
||
" # 写入总表\n",
|
||
" final_all.to_excel(writer, sheet_name='总表', index=False)\n",
|
||
"\n",
|
||
" # 写入每个门店的 sheet\n",
|
||
" for sheet_name, df_sheet in results_by_store.items():\n",
|
||
" # sheet 名称不能超过 31 字符,且不能有非法字符\n",
|
||
" safe_sheet_name = sheet_name[:31].replace(':', '').replace('/', '').replace('\\\\', '')\n",
|
||
" df_sheet.to_excel(writer, sheet_name=safe_sheet_name, index=False)\n",
|
||
"\n",
|
||
"print(f\"\\n✅ 异常检测完成,结果已保存至 '{output_file}'\")"
|
||
],
|
||
"id": "5d403c98ebb5b95d",
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"\n",
|
||
"正在处理门店: 四元桥奥迪店\n",
|
||
"✅ 门店 四元桥奥迪店 的会员卡使用占比为 15.8%\n",
|
||
"\n",
|
||
"正在处理门店: 四元桥奔驰店\n",
|
||
"✅ 门店 四元桥奔驰店 的会员卡使用占比为 1.4%\n",
|
||
"\n",
|
||
"正在处理门店: 回龙观分公司\n",
|
||
"✅ 门店 回龙观分公司 的会员卡使用占比为 7.5%\n",
|
||
"\n",
|
||
"正在处理门店: 张家口分公司\n",
|
||
"✅ 门店 张家口分公司 的会员卡使用占比为 83.1%\n",
|
||
"\n",
|
||
"✅ 异常检测完成,结果已保存至 '门店异常检测结果_多模型.xlsx'\n"
|
||
]
|
||
}
|
||
],
|
||
"execution_count": 25
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-06-27T06:54:59.085858Z",
|
||
"start_time": "2025-06-27T06:54:58.384642Z"
|
||
}
|
||
},
|
||
"cell_type": "code",
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"\n",
|
||
"file_path = r\"D:\\Idea Project\\F6+宜搭+其它(1)\\new\\文件输入\\孤立森林数据1 2025-06-27 11-42-26.xlsx\"\n",
|
||
"df = pd.read_excel(file_path)\n",
|
||
"\n",
|
||
"# 所有原始特征\n",
|
||
"original_features = ['销售金额(除税)', '销售内容(销售量)', '会员卡ID(会员数量)', '客户ID(客户数量)']\n",
|
||
"# 主循环处理每个门店\n",
|
||
"for item in original_features:\n",
|
||
" means = df[item].mean() # 每列的均值\n",
|
||
" stds = df[item].std()\n",
|
||
"\n",
|
||
" print(\"均值:\")\n",
|
||
" print(means)\n",
|
||
" \n",
|
||
" print(\"\\n标准差:\")\n",
|
||
" print(stds)\n",
|
||
"\n",
|
||
"# from scipy import stats\n",
|
||
"# \n",
|
||
"# # 计算Z分数\n",
|
||
"# z_scores = df.apply(stats.zscore)\n",
|
||
"# \n",
|
||
"# # 找出绝对Z分数大于3的行和列\n",
|
||
"# outliers = (abs(z_scores) > 3)\n",
|
||
"# \n",
|
||
"# # 输出异常值的位置\n",
|
||
"# print(\"大于3标准差的数据位置:\")\n",
|
||
"# print(outliers)\n",
|
||
"# \n",
|
||
"# # 如果你想查看实际的数据而不是True/False标志,可以这样操作:\n",
|
||
"# outlier_data = df[outliers]\n",
|
||
"# print(\"\\n大于3标准差的实际数据:\")\n",
|
||
"# print(outlier_data)"
|
||
],
|
||
"id": "ca0cba6975b555a4",
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"均值:\n",
|
||
"53739.5671507889\n",
|
||
"\n",
|
||
"标准差:\n",
|
||
"59128.62644709043\n",
|
||
"均值:\n",
|
||
"241.1657693397563\n",
|
||
"\n",
|
||
"标准差:\n",
|
||
"180.35306456565837\n",
|
||
"均值:\n",
|
||
"3.2700481722867667\n",
|
||
"\n",
|
||
"标准差:\n",
|
||
"8.114746173984752\n",
|
||
"均值:\n",
|
||
"241.16293567582883\n",
|
||
"\n",
|
||
"标准差:\n",
|
||
"180.34589569833363\n"
|
||
]
|
||
}
|
||
],
|
||
"execution_count": 29
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Python 3",
|
||
"language": "python",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 2
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython2",
|
||
"version": "2.7.6"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|