You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1470 lines
84 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"id": "fecd214a",
"metadata": {},
"source": [
"python 3.6.13\n",
"matplotlib 3.3.4\n",
"numpy 1.19.2\n",
"pandas 1.1.5\n",
"scikit-learn 0.24.2\n",
"seaborn 0.11.2\n",
"sqlalchemy 1.4.22"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "12d24a6c",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.cluster import KMeans\n",
"from sklearn.metrics import silhouette_score\n",
"from sqlalchemy import create_engine\n",
"from urllib.parse import quote_plus as urlquote\n",
"import datetime\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"import seaborn as sns\n",
"import time"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "121a3f95",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:31.824351Z",
"start_time": "2022-01-05T07:53:31.780403Z"
}
},
"outputs": [],
"source": [
"db_password = 'POMS_129@MySQL'\n",
"db_engine = create_engine(f'mysql+pymysql://poms:{urlquote(db_password)}@101.133.164.208:3306/dev_poms?charset=utf8')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "faa12069",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:32.314051Z",
"start_time": "2022-01-05T07:53:31.827278Z"
}
},
"outputs": [],
"source": [
"sql = \"SELECT `create_user` AS `account`, `point_uuid`, `point`, `create_time` FROM `sys_point_record` WHERE `audited` = 1\"\n",
"raw_data = pd.read_sql(sql, db_engine)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "8120b8c2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>account</th>\n",
" <th>point_uuid</th>\n",
" <th>point</th>\n",
" <th>create_time</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1951134</td>\n",
" <td>681cb6da8c9a4984ab6bf5c39bc9cfdc</td>\n",
" <td>9</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2051111</td>\n",
" <td>8312dac5b3cf5d93b511b1111a9aad30</td>\n",
" <td>6</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1951122</td>\n",
" <td>b2f8e1aa52697d4088f0c3d27cf5fd01</td>\n",
" <td>2</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2051110</td>\n",
" <td>afe319c5b9cec39700d219bc2cb55137</td>\n",
" <td>4</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1951122</td>\n",
" <td>afe319c5b9cec39700d219bc2cb55137</td>\n",
" <td>2</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76045</th>\n",
" <td>5396174</td>\n",
" <td>b2f8e1aa52697d4088f0c3d27cf5fd01</td>\n",
" <td>7</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76046</th>\n",
" <td>2051107</td>\n",
" <td>a373d0b08d8f3698f94c4a81d070bc3d</td>\n",
" <td>9</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76047</th>\n",
" <td>2051102</td>\n",
" <td>dde9d4a8db4ec74a39e3ceae0734815f</td>\n",
" <td>4</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76048</th>\n",
" <td>1951130</td>\n",
" <td>6f99a016eb26d149cc3eb2ef4ea5bba8</td>\n",
" <td>3</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76049</th>\n",
" <td>1951129</td>\n",
" <td>136e05d5470d9e843d699e1bc10bd17a</td>\n",
" <td>5</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>76050 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" account point_uuid point create_time\n",
"0 1951134 681cb6da8c9a4984ab6bf5c39bc9cfdc 9 2021-01-01\n",
"1 2051111 8312dac5b3cf5d93b511b1111a9aad30 6 2021-01-01\n",
"2 1951122 b2f8e1aa52697d4088f0c3d27cf5fd01 2 2021-01-01\n",
"3 2051110 afe319c5b9cec39700d219bc2cb55137 4 2021-01-01\n",
"4 1951122 afe319c5b9cec39700d219bc2cb55137 2 2021-01-01\n",
"... ... ... ... ...\n",
"76045 5396174 b2f8e1aa52697d4088f0c3d27cf5fd01 7 2021-12-29\n",
"76046 2051107 a373d0b08d8f3698f94c4a81d070bc3d 9 2021-12-29\n",
"76047 2051102 dde9d4a8db4ec74a39e3ceae0734815f 4 2021-12-29\n",
"76048 1951130 6f99a016eb26d149cc3eb2ef4ea5bba8 3 2021-12-29\n",
"76049 1951129 136e05d5470d9e843d699e1bc10bd17a 5 2021-12-29\n",
"\n",
"[76050 rows x 4 columns]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 看一眼\n",
"raw_data"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "c1954360",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:32.439640Z",
"start_time": "2022-01-05T07:53:32.365840Z"
}
},
"outputs": [],
"source": [
"# 去除缺失值\n",
"df2 = raw_data.copy().fillna(0)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "1f387b2f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>account</th>\n",
" <th>point_uuid</th>\n",
" <th>point</th>\n",
" <th>create_time</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1951134</td>\n",
" <td>681cb6da8c9a4984ab6bf5c39bc9cfdc</td>\n",
" <td>9</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2051111</td>\n",
" <td>8312dac5b3cf5d93b511b1111a9aad30</td>\n",
" <td>6</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1951122</td>\n",
" <td>b2f8e1aa52697d4088f0c3d27cf5fd01</td>\n",
" <td>2</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2051110</td>\n",
" <td>afe319c5b9cec39700d219bc2cb55137</td>\n",
" <td>4</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1951122</td>\n",
" <td>afe319c5b9cec39700d219bc2cb55137</td>\n",
" <td>2</td>\n",
" <td>2021-01-01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76045</th>\n",
" <td>5396174</td>\n",
" <td>b2f8e1aa52697d4088f0c3d27cf5fd01</td>\n",
" <td>7</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76046</th>\n",
" <td>2051107</td>\n",
" <td>a373d0b08d8f3698f94c4a81d070bc3d</td>\n",
" <td>9</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76047</th>\n",
" <td>2051102</td>\n",
" <td>dde9d4a8db4ec74a39e3ceae0734815f</td>\n",
" <td>4</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76048</th>\n",
" <td>1951130</td>\n",
" <td>6f99a016eb26d149cc3eb2ef4ea5bba8</td>\n",
" <td>3</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76049</th>\n",
" <td>1951129</td>\n",
" <td>136e05d5470d9e843d699e1bc10bd17a</td>\n",
" <td>5</td>\n",
" <td>2021-12-29</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>76050 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" account point_uuid point create_time\n",
"0 1951134 681cb6da8c9a4984ab6bf5c39bc9cfdc 9 2021-01-01\n",
"1 2051111 8312dac5b3cf5d93b511b1111a9aad30 6 2021-01-01\n",
"2 1951122 b2f8e1aa52697d4088f0c3d27cf5fd01 2 2021-01-01\n",
"3 2051110 afe319c5b9cec39700d219bc2cb55137 4 2021-01-01\n",
"4 1951122 afe319c5b9cec39700d219bc2cb55137 2 2021-01-01\n",
"... ... ... ... ...\n",
"76045 5396174 b2f8e1aa52697d4088f0c3d27cf5fd01 7 2021-12-29\n",
"76046 2051107 a373d0b08d8f3698f94c4a81d070bc3d 9 2021-12-29\n",
"76047 2051102 dde9d4a8db4ec74a39e3ceae0734815f 4 2021-12-29\n",
"76048 1951130 6f99a016eb26d149cc3eb2ef4ea5bba8 3 2021-12-29\n",
"76049 1951129 136e05d5470d9e843d699e1bc10bd17a 5 2021-12-29\n",
"\n",
"[76050 rows x 4 columns]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 看一眼\n",
"df2"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "c423e07e",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:41.383720Z",
"start_time": "2022-01-05T07:53:32.508456Z"
}
},
"outputs": [],
"source": [
"## Recent【最近一次消费数据】\n",
"now = pd.to_datetime(datetime.datetime.now())\n",
"# 添加时间差数据\n",
"df2[\"recent\"] = df2[\"create_time\"].map(lambda x: (now - pd.to_datetime(x)).days)\n",
"# 用户最近一次购买商品的时间\n",
"recent_df = df2.groupby(by=\"account\", as_index=False).agg({\"recent\": \"min\"})"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "dc957d34",
"metadata": {},
"outputs": [],
"source": [
"## Frequency【一段时间内的消费次数】\n",
"frequency_df = df2.groupby(by=\"account\", as_index=False).agg({\"point_uuid\": \"count\"})"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "308bc08d",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:41.636044Z",
"start_time": "2022-01-05T07:53:41.593163Z"
}
},
"outputs": [],
"source": [
"## Mount【一段时间内的消费总金额】\n",
"mount_df = df2.groupby(by=\"account\", as_index=False).agg({\"point\": \"sum\"})"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "de978fb4",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:41.760711Z",
"start_time": "2022-01-05T07:53:41.671948Z"
}
},
"outputs": [],
"source": [
"## RFM模型\n",
"# 根据 account 合并数据\n",
"rfm_df = recent_df.merge(frequency_df, on=\"account\", how=\"left\").merge(mount_df, on=\"account\", how=\"left\")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "dc4af967",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:41.806587Z",
"start_time": "2022-01-05T07:53:41.794621Z"
}
},
"outputs": [],
"source": [
"rfm_df2 = rfm_df.copy()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "0c145514",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:41.883382Z",
"start_time": "2022-01-05T07:53:41.840497Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0.0 0\n",
"0.2 2\n",
"0.4 4\n",
"0.6 6\n",
"0.8 8\n",
"1.0 13057\n",
"Name: point, dtype: int64"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rfm_df2[\"point\"].quantile(q=np.linspace(0, 1, num=6), interpolation='nearest')"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "3d49d903",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>account</th>\n",
" <th>recent</th>\n",
" <th>point_uuid</th>\n",
" <th>point</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1001611</td>\n",
" <td>464</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1005374</td>\n",
" <td>589</td>\n",
" <td>1</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1005407</td>\n",
" <td>624</td>\n",
" <td>1</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1010153</td>\n",
" <td>756</td>\n",
" <td>1</td>\n",
" <td>10</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1010528</td>\n",
" <td>467</td>\n",
" <td>1</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5881</th>\n",
" <td>9990197</td>\n",
" <td>809</td>\n",
" <td>1</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5882</th>\n",
" <td>9990991</td>\n",
" <td>573</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5883</th>\n",
" <td>9992257</td>\n",
" <td>666</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5884</th>\n",
" <td>9993826</td>\n",
" <td>498</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5885</th>\n",
" <td>9998323</td>\n",
" <td>734</td>\n",
" <td>1</td>\n",
" <td>7</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5886 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" account recent point_uuid point\n",
"0 1001611 464 1 4\n",
"1 1005374 589 1 7\n",
"2 1005407 624 1 5\n",
"3 1010153 756 1 10\n",
"4 1010528 467 1 7\n",
"... ... ... ... ...\n",
"5881 9990197 809 1 8\n",
"5882 9990991 573 1 4\n",
"5883 9992257 666 1 0\n",
"5884 9993826 498 1 0\n",
"5885 9998323 734 1 7\n",
"\n",
"[5886 rows x 4 columns]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rfm_df2"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "605888d7",
"metadata": {},
"outputs": [],
"source": [
"# 根据分位数分层划分为5个等级\n",
"recent_labels = [5, 4, 3, 2, 1]\n",
"mount_labels = [1, 2, 3, 4, 5]\n",
"frequency_bins = [1, 3, 5, 12]\n",
"frequency_labels = [1, 2, 3]\n",
"\n",
"m_bins = rfm_df2[\"point\"].quantile(q=np.linspace(0, 1, num=6), interpolation='nearest')\n",
"r_bins = rfm_df2[\"recent\"].quantile(q=np.linspace(0, 1, num=6), interpolation='nearest')\n",
"rfm_df2[\"R\"] = pd.cut(rfm_df2[\"recent\"], bins=r_bins, labels=recent_labels, include_lowest=True)\n",
"rfm_df2[\"F\"] = pd.cut(rfm_df2[\"point_uuid\"], bins=frequency_bins, labels=frequency_labels, include_lowest=True)\n",
"rfm_df2[\"M\"] = pd.cut(rfm_df2[\"point\"], bins=m_bins, labels=mount_labels, include_lowest=True)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "6dbd63f1",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>account</th>\n",
" <th>R</th>\n",
" <th>F</th>\n",
" <th>M</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1001611</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1005374</td>\n",
" <td>4</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1005407</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1010153</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1010528</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5881</th>\n",
" <td>9990197</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5882</th>\n",
" <td>9990991</td>\n",
" <td>4</td>\n",
" <td>1</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5883</th>\n",
" <td>9992257</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5884</th>\n",
" <td>9993826</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5885</th>\n",
" <td>9998323</td>\n",
" <td>2</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5886 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" account R F M\n",
"0 1001611 5 1 2\n",
"1 1005374 4 1 4\n",
"2 1005407 3 1 3\n",
"3 1010153 1 1 5\n",
"4 1010528 5 1 4\n",
"... ... .. .. ..\n",
"5881 9990197 1 1 4\n",
"5882 9990991 4 1 2\n",
"5883 9992257 3 1 1\n",
"5884 9993826 5 1 1\n",
"5885 9998323 2 1 4\n",
"\n",
"[5886 rows x 4 columns]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 删除不需要的列\n",
"rfm_df2 = rfm_df2.drop(['recent', 'point_uuid', 'point'], axis=1)\n",
"rfm_df2"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "c81fdc73",
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-05T07:53:42.199538Z",
"start_time": "2022-01-05T07:53:42.187570Z"
}
},
"outputs": [],
"source": [
"rfm_df2 = rfm_df2.fillna(3)\n",
"rfm_df2 = rfm_df2.astype(int)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "8e19592c",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>account</th>\n",
" <th>R</th>\n",
" <th>F</th>\n",
" <th>M</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1001611</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1005374</td>\n",
" <td>4</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1005407</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1010153</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1010528</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5881</th>\n",
" <td>9990197</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5882</th>\n",
" <td>9990991</td>\n",
" <td>4</td>\n",
" <td>1</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5883</th>\n",
" <td>9992257</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5884</th>\n",
" <td>9993826</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5885</th>\n",
" <td>9998323</td>\n",
" <td>2</td>\n",
" <td>1</td>\n",
" <td>4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5886 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" account R F M\n",
"0 1001611 5 1 2\n",
"1 1005374 4 1 4\n",
"2 1005407 3 1 3\n",
"3 1010153 1 1 5\n",
"4 1010528 5 1 4\n",
"... ... .. .. ..\n",
"5881 9990197 1 1 4\n",
"5882 9990991 4 1 2\n",
"5883 9992257 3 1 1\n",
"5884 9993826 5 1 1\n",
"5885 9998323 2 1 4\n",
"\n",
"[5886 rows x 4 columns]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rfm_df2"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "1a033585",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"# 对数据进行提取选取我们需要的列\n",
"rfm = rfm_df2[['R', 'F', 'M']]\n",
"#使用lambda函数对数据进行归一化处理\n",
"normalization_rfm = rfm.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x)))"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "1b20e949",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>R</th>\n",
" <th>F</th>\n",
" <th>M</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.00</td>\n",
" <td>0.0</td>\n",
" <td>0.25</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.75</td>\n",
" <td>0.0</td>\n",
" <td>0.75</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.50</td>\n",
" <td>0.0</td>\n",
" <td>0.50</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>1.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1.00</td>\n",
" <td>0.0</td>\n",
" <td>0.75</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5881</th>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.75</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5882</th>\n",
" <td>0.75</td>\n",
" <td>0.0</td>\n",
" <td>0.25</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5883</th>\n",
" <td>0.50</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5884</th>\n",
" <td>1.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5885</th>\n",
" <td>0.25</td>\n",
" <td>0.0</td>\n",
" <td>0.75</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5886 rows × 3 columns</p>\n",
"</div>"
],
"text/plain": [
" R F M\n",
"0 1.00 0.0 0.25\n",
"1 0.75 0.0 0.75\n",
"2 0.50 0.0 0.50\n",
"3 0.00 0.0 1.00\n",
"4 1.00 0.0 0.75\n",
"... ... ... ...\n",
"5881 0.00 0.0 0.75\n",
"5882 0.75 0.0 0.25\n",
"5883 0.50 0.0 0.00\n",
"5884 1.00 0.0 0.00\n",
"5885 0.25 0.0 0.75\n",
"\n",
"[5886 rows x 3 columns]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"normalization_rfm = normalization_rfm.fillna(0)\n",
"normalization_rfm"
]
},
{
"cell_type": "markdown",
"id": "3a13399c",
"metadata": {},
"source": [
"$$\n",
"SSE = \\sum^{k}_{i=1}\\sum_{p\\in{C_i}}|p-m_i|^2\n",
"$$\n",
"$C_i$是第$i$个簇,$p$是$C_i$中的样本点,$m_i$是$C_i$的质心($C_i$中所有样本的均值),$SSE$是所有样本的聚类误差,代表了聚类效果的好坏。"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "422c054b",
"metadata": {},
"outputs": [],
"source": [
"clusters = [2, 3, 4, 5, 6, 7, 8]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "a0c1889b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[934.2103968347631, 597.3608447740422, 384.3004298136629, 317.9862632164778, 271.5227306631748, 231.6340074056924, 196.15821396905733]\n"
]
}
],
"source": [
"# 手肘法来确定最优K值\n",
"SSE = [] # 误差平方和\n",
"SC = [] # 轮廓系数\n",
"for i in clusters:\n",
" kmeans = KMeans(n_clusters=i)\n",
" kmeans.fit(normalization_rfm)\n",
" SSE.append(kmeans.inertia_)\n",
"print(SSE)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "a50606ef",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0, 0.5, 'SSE')"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEECAYAAAAlEzNMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAqyUlEQVR4nO3deXzU9b3v8dcsmSwzkwyEBKEhkCAhLMZEkd0oxyW21i0qSFqwR2sl9dSGWy1LNdiHHpHrrVJtPaBF7Y3FkAou154jUooGoUYKIohEJewkQNhnhjiZJHP/CMSgEjGZyWzv5+Ph4wET5pfPx9G8+X2X39fg8/l8iIhI1DIGuwAREQkuBYGISJRTEIiIRDkFgYhIlFMQiIhEOXOwC/iuWlpaaG7u3EInk8nQ6feGGvUSeiKlD1AvoaorvcTEmM76tbALguZmH8eOnezUex2OhE6/N9Sol9ATKX2AeglVXeklJcV+1q9paEhEJMopCEREopyCQEQkyikIRESinIJARCTKKQhERKKcgkBEJMpFTRAcOdnIf2+uQ0/dFhE5U9QEwUf7TvDLio9Ys+NIsEsREQkpURMEl2b2JLOXld+/u52m5pZglyMiEjKiJgjMJiMzrhnMziMNLNu0P9jliIiEjKgJAoAJWSlcku7g2bU7cX7RFOxyRERCQlQFgcFgoOSyTE580cTzVbuDXY6ISEiIqiAAyEq1cd3w3iz5cB97jzUEuxwRkaCLuiAAmDZuAGajgT+s3hHsUkREgi4g5xE0NjYya9Ys9uzZg81mo7S0FIPBwMyZMzEYDAwaNIg5c+ZgNBqpqKigvLwcs9lMcXExEyZMCERJZ0ixxTL1kn4sXLuLjXuPk5uWFPDvKSISqgISBBUVFSQkJFBRUcH27dt5+OGHiYmJoaSkhFGjRlFaWsrKlSvJzc2lrKyMpUuX4vF4KCoqYty4cVgslkCUdYYfj0jj1U11PPnudl4oysVoMAT8e4qIhKKABMG2bdvIz88HIDMzk5qaGpqbmxk5ciQA+fn5rFmzBqPRSF5eHhaLBYvFQnp6OtXV1eTk5Jz12iaTAYcjoVN1mUzGM957f8Fg7l+6mdW7j3PDhX07dc1g+Wov4SxSeomUPkC9hKpA9RKQIBgyZAirVq3iyiuv5KOPPuLAgQMkJydjOPW3bqvVitPpxOVyYbd/eXya1WrF5XJ1eG1/HlWZ39/BkN42/vdb1YzqayeugzM9Q42O3ws9kdIHqJdQFVZHVd58883YbDamTp3KqlWrGDZsGEbjl9/K7XaTmJiIzWbD7Xaf8Xr7YAg0o8FAyeWZHHQ1snj9vm77viIioSQgQbB582YuvvhiysrKuPLKK+nXrx9Dhw6lqqoKgMrKSkaMGEFOTg7r16/H4/HgdDqpqakhKysrECWd1UVpDiYM6sWLH+zmkLuxW7+3iEgoCMjQUP/+/fn973/P888/j91u5z//8z85efIkDz74IE888QSZmZkUFBRgMpmYMmUKRUVF+Hw+pk+fTmxsbCBK6tAvLs1gdc1hFqzZyQNXd28QiYgEm8EXZs9l9nqb/TZH0N6T79Tw8vp9vDTlIrJSbV0psVto3DP0REofoF5CVVjNEYSjO0enkxhnZv6723VmgYhEFQXBKYlxMdw1pj/rdh/TmQUiElUUBO3cfGEf0nvE68wCEYkqCoJ2zCYjv7wsk51HGnh1s84sEJHooCD4ikszezIi3cGza3fpzAIRiQoKgq84fWbB8QYvL+jMAhGJAgqCbzA41cYPh/WmXGcWiEgUUBCcRfH4AZgMBv6oMwtEJMIpCM4ixRbL1JH9+Ptnh/ho3/FglyMiEjAKgg78eEQaqTYLT76znRZtMhORCKUg6EB8jImfj89gy34nb1fXB7scEZGAUBB8i+8PTSU71cYfVu/gC29zsMsREfE7BcG3OH1mwQGnh5c36MwCEYk8CoJzcHE/B5efn8yLVXt0ZoGIRBwFwTn6RX4mjc0tLFyzM9iliIj4lYLgHKX3iGdiXl/e+Hg/n9d3fK6yiEg4URB8B3eOTscea2b+OzqzQEQih4LgO0iMi+GnY/rzwe5jrN1xNNjliIj4hYLgO7ql/ZkFLborEJHwF5Ag8Hq9/OpXv+K2226jqKiImpoadu3axeTJkykqKmLOnDm0tLQe/FJRUUFhYSETJ05k1apVgSjHr8wmI/fmZ7LjyEle21QX7HJERLrMHIiLvvvuuzQ1NVFeXs6aNWuYP38+Xq+XkpISRo0aRWlpKStXriQ3N5eysjKWLl2Kx+OhqKiIcePGYbFYAlGW3+QP7MmIfkksXLuLa4akYosNyL9GEZFuEZCfYBkZGTQ3N9PS0oLL5cJsNrNx40ZGjhwJQH5+PmvWrMFoNJKXl4fFYsFisZCenk51dTU5OTlnvbbJZMDhSOhUXSaTsdPv/aoHfjiMmxasZfHGOn5dMNgv1/wu/NlLsEVKL5HSB6iXUBWoXgISBAkJCezbt4/vf//7HD16lAULFrBu3ToMBgMAVqsVp9OJy+XCbre3vc9qteJydbw0s7nZx7FjJztVl8OR0On3ftX3EsxcO7Q3L/5zJ9dm9+J7SfF+ue658mcvwRYpvURKH6BeQlVXeklJsZ/1awGZI3jxxRcZP348y5cv5/XXX2fmzJl4vd62r7vdbhITE7HZbLjd7jNebx8Moa54XOuZBX+o3BnsUkREOi0gQZCYmNj2Az0pKYmmpiaGDh1KVVUVAJWVlYwYMYKcnBzWr1+Px+PB6XRSU1NDVlZWIEoKiFR7LFMv6cffP6vXmQUiErYMvgDsjHK73cyePZv6+nq8Xi9Tp05l+PDhPPjgg3i9XjIzM3nkkUcwmUxUVFSwZMkSfD4fd999NwUFBR1e2+ttDomhodMavM3c/Pw6Um2xPF+Ui/HU8Feg6XY39ERKH6BeQlWghoYCEgSBFGpBAPDmlv389q3PeOQH2RQMSfX79b+J/uMOPZHSB6iXUBVWcwTR5gdDe+vMAhEJWwoCPzh9ZsF+nVkgImFIQeAn7c8sOKwzC0QkjCgI/OgX+Zl4mltYuHZnsEsRETlnCgI/Su8Rz8Tcvry+eT/b6t3f/gYRkRCgIPCzO0enY4s1M//dGp1ZICJhQUHgZ0nxrWcWVO06xtqdOrNAREKfgiAA2s4seEdnFohI6FMQBECMyci9+Rk6s0BEwoKCIEDyByZzcb8knl27C5enKdjliIiclYIgQAwGAyWXZXKswcsLVXuCXY6IyFkpCAIou7edHwzrzcsb9rLveEOwyxER+UYKggD7+bgBGA0G/rh6Z7BLERH5RgqCAGs9syCNFZ/Ws6n2RLDLERH5GgVBN5hyST96WS08+Y42mYlI6FEQdIP4GBM/Hz+Aj+ucrPi0PtjliIicQUHQTa4d1pvBqTaertSZBSISWhQE3cR4ajnpfqeHcp1ZICIhxByIiy5btoxXX30VAI/Hw9atW1m8eDGPPvooBoOBQYMGMWfOHIxGIxUVFZSXl2M2mykuLmbChAmBKCkkjEh3cNnAZF78YA/XDT+PZKsl2CWJiATmjqCwsJCysjLKysoYNmwYDzzwAH/84x8pKSlh8eLF+Hw+Vq5cSX19PWVlZZSXl7No0SKeeOIJGhsj+1CXX+Rn8EVTC8+u3RXsUkREgAAPDW3evJlt27YxadIktmzZwsiRIwHIz89n7dq1bNq0iby8PCwWC3a7nfT0dKqrqwNZUtD175nArbl9eW1zHdsO6cwCEQm+gAwNnbZw4ULuueceAHw+HwaDAQCr1YrT6cTlcmG329v+vNVqxeVydXhNk8mAw5HQqXpMJmOn3+tPvyoYzP9sPcgza3bx/O0jOnWNUOnFHyKll0jpA9RLqApULwELghMnTrB9+3ZGjx4NgNH45c2H2+0mMTERm82G2+0+4/X2wfBNmpt9HDt2slM1ORwJnX6vv90xqh9PvrOd//5wL2Mzen7n94dSL10VKb1ESh+gXkJVV3pJSTn7z9aADQ2tW7eOsWPHtv1+6NChVFVVAVBZWcmIESPIyclh/fr1eDwenE4nNTU1ZGVlBaqkkHJrbl/6OeKY/67OLBCR4ApYEOzYsYO0tLS238+YMYOnn36aSZMm4fV6KSgoICUlhSlTplBUVMTtt9/O9OnTiY2NDVRJIaX1zIJMdhw+yeubdWaBiASPwRdmzzzwepsjYmgIWudNplVsYsfhkyy78xJssec+UhdqvXRFpPQSKX2AeglVYTc0JN/OYDAw/fLWMwte/EBnFohIcCgIgqztzIL1e6k9/kWwyxGRKKQgCAE/HzcAg8HAH1fvCHYpIhKFFAQhINUey5QRabytMwtEJAgUBCHi9JkF83VmgYh0MwVBiEiwmCgeP4DNOrNARLqZgiCEXDu0N1kpVv6wegeeppZglyMiUUJBEEJMRgMll2dSd0JnFohI91EQhJhL0nuQPzCZF6p2c+RkZD+SW0RCg4IgBOnMAhHpTgqCEDSgZwK3XNiHVzfVUaMzC0QkwBQEIeqnY/pjtZj5/bvbg12KiEQ4BUGIcsTH8NMx6fxz51HW7jgS7HJEJIIpCELY6TMLfq8zC0QkgBQEISzGZOQX+ZlsP3ySN3RmgYgEiIIgxF1+fjJ5aUksWLMLl6cp2OWISARSEIS402cWHG3w8medWSAiAaAgCANDetu5dmgqi9fvpe6EziwQEf9SEISJ4vEZOrNARAIiYEGwcOFCJk2aRGFhIX/961/ZtWsXkydPpqioiDlz5tDS0vpQtYqKCgoLC5k4cSKrVq0KVDlhr7c9lh+PSGN5dT2bdWaBiPhRQIKgqqqKDz/8kJdffpmysjL279/P3LlzKSkpYfHixfh8PlauXEl9fT1lZWWUl5ezaNEinnjiCRob9Xyds5l6ST+SrRaefGe7ziwQEb8JSBC89957ZGVlcc899zBt2jQuv/xytmzZwsiRIwHIz89n7dq1bNq0iby8PCwWC3a7nfT0dKqrqwNRUkRIsJj4+bgBbK47wf98vD/Y5YhIhDAH4qJHjx6ltraWBQsWsHfvXoqLi/H5fBgMBgCsVitOpxOXy4Xdbm97n9VqxeVydXhtk8mAw5HQqbpMJmOn3xsqfjQug1c21fHbN7ey5GejGJBsDXZJXRYJnwtETh+gXkJVoHoJSBA4HA4yMzOxWCxkZmYSGxvL/v1f/g3W7XaTmJiIzWbD7Xaf8Xr7YPgmzc0+jh072cm6Ejr93lDyyA+y+Wn5Rv79xXUsmpxLzwRLsEvqkkj5XCKlD1AvoaorvaSknP1na4dDQwcPHvzG1z/66KMOv+HFF1/M6tWr8fl8HDhwgIaGBsaMGUNVVRUAlZWVjBgxgpycHNavX4/H48HpdFJTU0NWVta39RP10nvE8+yPL6be1UjJso852dgc7JJEJIx1GAT33Xdf26/vv//+tl//7ne/6/CiEyZMYMiQIdxyyy0UFxdTWlrKjBkzePrpp5k0aRJer5eCggJSUlKYMmUKRUVF3H777UyfPp3Y2NguthQdcvs5mPvDIXx60MXsN7fqWUQi0mkdDg21X5nSfmjnXFas/PrXv/7aay+99NLXXps4cSITJ0781uvJ1106MJkZVw5i7orPeWzF5/zm6kFt8zAiIueqU3ME+mETOgpz+nDQ6WHR+7tJtVv42dgBwS5JRMJMh0HQ/ge+fviHrrvH9ueg08Nz/9xNii2Wm3L6BLskEQkjHQbBhg0bGD9+PADHjh1r+/Xx48cDX5mcM4PBwOyrBnHI3ci8v39OL6uFSwcmB7ssEQkTHQbBxx9/3F11SBeZTUYeu24o0yo+YvabW1kwMYdhfRKDXZaIhIEOVw01Njby5z//uW0Z6L333st9991HfX19d9Un30GCxcSTNw0n2Wqh5NUt7DnaEOySRCQMdBgEDz/8MLW1tbS0tPDQQw+RnZ1NQUEBDz30UDeVJ99VstXCUzdfAMAvlm7msFvPbhKRjnUYBLW1tcyaNYumpibWr1/PXXfdxVVXXcWRIzpMPZSl94jnyZuGccjdyPRXteFMRDrWYRCcXim0YcMGLrjgAmJiYgDweDyBr0y6ZHifxLYNZ7Pe/ISm5pZglyQiIarDIEhISGDJkiU899xzXHvttbS0tPDXv/6VPn20PDEcnN5wtnbHUeb+/XM9ulpEvlGHQfDQQw+xe/durrjiCgoLC1m5ciVvvvmm5gjCSGFOH+4cnc4bHx/guX/uCnY5IhKCOgyCuro63nvvPSZOnMjbb7/NnDlz2L9/P5s3b+6u+sQP7h7bn+uG9ea5f+7m1U11wS5HREJMh0Hw5JNPMm/ePGJiYpg/fz7PPfccS5cu5dlnn+2u+sQPTm84G5vRg3l//5zVNYeDXZKIhJAOg8Dn85Gdnd32KOlhw4Zhs9kwGnXmfbgxm4zM/eFQslJtzHpzKx/X6dxjEWnV4U/00wfMr169mjFjxgCtm8zaHyYj4eP0hrNeVgvTX93Cbm04ExG+JQjGjBnDbbfdxh/+8AemTJnC7t27mTZtGj/4wQ+6qz7xs/Ybzu7VhjMRAQy+b1lTWFNTQ8+ePenRowe7d+/m008/5aqrruqu+r7G622O+qMqoeu9fFx3gmkVm8hMTmDBxAtJsJj8WN13EymfS6T0AeolVAXlqEqAgQMH0qNHDwDS09ODGgLiP9pwJiKnadY3imnDmYhAJ08ok8hRmNOHeqeHP72/m972WJ1wJhKFAhYEN954I3Z765hUWloa06ZNY+bMmRgMBgYNGsScOXMwGo1UVFRQXl6O2WymuLiYCRMmBKokOYufje3PQZdOOBOJVgEJgtMPpSsrK2t7bdq0aZSUlDBq1ChKS0tZuXIlubm5lJWVsXTpUjweD0VFRYwbNw6LxRKIsuQsDAYDs65sPeHsMZ1wJhJ1AjJHUF1dTUNDA3fccQdTp05l48aNbNmyhZEjRwKQn5/P2rVr2bRpE3l5eVgsFux2O+np6VRXVweiJPkWpzecDdaGM5GoE5A7gri4OO68805uvfVWdu7cyV133YXP52t7rLXVasXpdOJyudqGj06/7nK5Ory2yWTA4UjoVF0mk7HT7w01gejFATz/k0uY+Oz7/K/XtlDxs9EMSLb69Xt8k0j5XCKlD1AvoSpQvQQkCDIyMujfvz8Gg4GMjAwcDgdbtmxp+7rb7SYxMRGbzXbGLmW3231GMHyT5maf9hEQuF7MwPybhnPnyxv5yQvrWDQ5l2RrYIfqIuVziZQ+QL2EqqDtI+iMV155hcceewyAAwcO4HK5GDduHFVVVQBUVlYyYsQIcnJyWL9+PR6PB6fTSU1NDVlZWYEoSb4DnXAmEl2+dWdxZzQ2NjJr1ixqa2sxGAzcd9999OjRgwcffBCv10tmZiaPPPIIJpOJiooKlixZgs/n4+6776agoKDDa2tncavu6GV1zWHue30Lowf04Hc3DMNsCsy2k0j5XCKlD1AvoSpQdwQBCYJAUhC06q5eXt1Ux6MrPuf64b154Oqstnkef4qUzyVS+gD1EqoCFQTaUCYduimnDwdPbThLtcVy97gBwS5JRPxMQSDf6vSGsz+9v5tUuzaciUQaBYF8K204E4lseuicnBNtOBOJXAoCOWcJFhPzC3XCmUikURDId9IzQSeciUQaBYF8Z9pwJhJZFATSKTrhTCRyKAik0y4dmMxMnXAmEva0fFS6RBvORMKfgkC6TBvORMKbgkC6TBvORMKb5gjEL7ThTCR8KQjEb7ThTCQ8KQjEr7ThTCT8KAjE77ThTCS8KAgkILThTCR8KAgkYNpvOHt0hTaciYQqLR+VgGq/4ay3XRvOREJRwO4IDh8+zGWXXUZNTQ27du1i8uTJFBUVMWfOHFpaWocJKioqKCwsZOLEiaxatSpQpUiQ/Wxsf64f3ps/vb+bZZvqgl2OiHxFQILA6/VSWlpKXFwcAHPnzqWkpITFixfj8/lYuXIl9fX1lJWVUV5ezqJFi3jiiSdobNQKk0h0esPZ2IwezPv756yuORzskkSknYAMDc2bN4/bbruNZ599FoAtW7YwcuRIAPLz81mzZg1Go5G8vDwsFgsWi4X09HSqq6vJycnp8NomkwGHI6FTdZlMxk6/N9SEYy/P/OhiprzwAbP/tpWyfx9Jbj8HEJ69fJNI6QPUS6gKVC9+D4Jly5bRs2dPLr300rYg8Pl8GAwGAKxWK06nE5fLhd1ub3uf1WrF5XJ96/Wbm30cO3ayU7U5HAmdfm+oCdde/s/1Q7lj8UbuKlvPosm5pPeID9tevipS+gD1Eqq60ktKiv2sX/P70NDSpUtZu3YtU6ZMYevWrcyYMYMjR460fd3tdpOYmIjNZsPtdp/xevtgkMikDWciocfvQfCXv/yFl156ibKyMoYMGcK8efPIz8+nqqoKgMrKSkaMGEFOTg7r16/H4/HgdDqpqakhKyvL3+VICErvEc/8m4Zx+NSGsxMN3mCXJBLVumUfwYwZM3j66aeZNGkSXq+XgoICUlJSmDJlCkVFRdx+++1Mnz6d2NjY7ihHQsCwPok8emrD2bjHVzH7za28u+0wjU3aeCbS3Qy+MNvl4/U2a46AyOnlk/1O3v78MH/bXMexBi/2WDP/ltWLguwULkpzYDIagl3iOYuUzwTUS6gK1ByBNpRJUA09z87Y7N78x9h0qnYfY/nWg6yoruf1zfvpZbVw1eAUCoakMrS3rW3BgYj4l4JAQoLZZGRcRk/GZfTkC28zq7cf4e3qg7zyUS0vb9hHP0ccV2enck12KgOSI2MpoEioUBBIyImLMXHV4BSuGpyC84smVn1+iLeqD/L8+7tZ9P5uBqfaKMhu/fp5iXHBLlck7CkIJKTZ48xcf8F5XH/BeRxyeVjx2SGWbz3IU5U7eKpyB3lpSRRkp3DFoBQcCTHBLlckLGmyOExFey97jjbw9qcHeWvrQXYeacBkNDBmQA+uzk7hsoG9SLCYAlTt2UX7ZxKq1EsrTRZLxOnXI547R/fnjlHpfFbv5u3qgyyvrue97UeINX9O/sBkCrJTGZvRgxiTnrYu0hEFgYQ1g8HA4FQbg1Nt3HNpBh/tO8Hy6oP8/dN6VnxaT2KcmQmDenFNdip5aUlhtRxVpLsoCCRiGA0G8tKSyEtL4r4JA6nadYzl1Qd5u/ogr2/eT4rt1HLU7FSGaDmqSBsFgUQks8nIuMyejMtsXY5aWXOYt6vrqfiwlsXrW5ejFmSnUqDlqCIKAol8cTEmrs5O5ersVE584T21HLWeRe/v5k/tlqNenZ1Kb7secyLRR0EgUSUxLoYbLujDDRf0od7lYcWn9Syvruepyh08XbmD3LQkrslO4d+yUnDEazmqRActHw1T6sW/9hxtYHn1QZZXn7kctSA7lfyByee0HDUU+vAX9RKatHxUJID69Yjnp2P6c+fo1uWoy7e2hsJ7248QZza2LkcdksqYAVqOKpFHQSDSTvvlqP+Rf+Zy1LdPLUf9t0G9uGZIKrnf03JUiQwKApGz+KblqG+dGj56rd1y1GuGpJKdagt2uSKdpiAQOQftl6M2eJtZXXOY5e2Wo6b3iOe6C/tyYW8bw86zYzFr+EjCh4JA5DuKb7cc9XhD63LU5dUHeebdGnw+iDUbGd7HzkVpSVyU5mB4HztxMd3/7CORc6UgEOmCpPgYbszpw405ffBZzFR+sp8Ne4+zYc9xFr2/m+d8uzEbDQw7z85F/ZK4KC2JnL5JQXkonsjZBCQImpubeeCBB9ixYwcmk4m5c+fi8/mYOXMmBoOBQYMGMWfOHIxGIxUVFZSXl2M2mykuLmbChAmBKEkk4HokWLjs/F5cdn4vAFyeJjbuO86He4+zYe9x/u8He3ihag8mA2T3PnXH0C+J3O8lYYvV38kkeALyX9+qVasAKC8vp6qqqi0ISkpKGDVqFKWlpaxcuZLc3FzKyspYunQpHo+HoqIixo0bh8ViCURZIt3KFmtmfGYy4zOTATjZ2Mym2uNtdwwvb9hH2b/2YjRAVoqNvLTWO4bctCRtZpNuFZAguPLKK7n88ssBqK2tpVevXrzzzjuMHDkSgPz8fNasWYPRaCQvLw+LxYLFYiE9PZ3q6mpycnICUZZIUCVYTIwe0JPRA3oC8IW3mY/rnGzYe4wNe4+zbFMdL2/YB8D5vaxcdGrFUl5aEslW/eVIAidg96Nms5kZM2awYsUKnnrqKVatWtX2tEer1YrT6cTlcmG3f7nbzWq14nK5OryuyWTA4ejcQ8JMJmOn3xtq1Evo6Uwf56XYuTKnLwCephY27zvOBzuO8MHOI7z5yQEqNtYCkNnLysiMnowc0INLBvQM+BGdkfKZgHo5FwEdmJw3bx733XcfEydOxOPxtL3udrtJTEzEZrPhdrvPeL19MHyT5mafHjGBeglF/ujj/KRYzs/tQ1FuH5qaW6g+6GLDntbhpP/3US3l6/YAkOaIa1uVdFG/JPr4ORgi5TMB9XJatz9i4rXXXuPAgQPcfffdxMfHYzAYGD58OFVVVYwaNYrKykpGjx5NTk4O8+fPx+Px0NjYSE1NDVlZWYEoSSTsmE1GhvdJZHifRKaO7Edzi4/P6l2tk897jvPOtsO88fEBAM6zx7atSroozUGaI07nLcg5C8hD506ePMmsWbM4dOgQTU1N3HXXXQwcOJAHH3wQr9dLZmYmjzzyCCaTiYqKCpYsWYLP5+Puu++moKCgw2vroXOt1Evo6e4+Wnw+ag652bDnOB/uaw2How1eAFJsFvK+l3QqHBwM6Bn/nYIhUj4TUC+ndXRHoKePhin1EnqC3YfP52PnkYbWyedTw0mH3I0A9EyIaZ14PhUOA3tZMXYQDMHuxZ/USys9fVQkChgMBjKSE8hITuDmC/vi8/nYe+yLtlVJG/YcZ+VnhwBIijOT23bHkMSgFJseoBfFFAQiEcpgMNCvRzz9esRzwwV9AKg78cWpu4XWcHi35jAAVoupNRhObXIbZQ/sqiQJLQoCkSjSJzGOa4fFce2w3gAcdHradj5v2HuMNTuOABAXYyQ71cbQ8+wMO8/O0PPsfC9JE9CRSkEgEsVS7bEUDEmlYEgqAIfdjWzcd5yth07y4a6jLP2ojsXrWze5JcWZGdanNRiGnZfI0PNs9EjQRrdIoCAQkTbJVgtXZKVw88jWScmm5hZqDp9ky34nn9Q52bLfyfs7d9NyaolJ36S4U8HQ+s/g3jbi9aTVsKMgEJGzMpuMbSe2Fea0zjOcbGym+qCTLXVOPtnv5OO6E6z4tB4Ak6F1F/TQduGQ2cuKWRPRIU1BICLfSYLF1LqjOc3R9tphdyOf7G+9Y9iy38mqzw/x+ub9QOv5DEN6fznfMKyPnb6Jmm8IJQoCEemyZKuFSwcmc+nA1ietnl662j4c2s83OOJj2u4YhvaxM6y3HUeCnrgaLAoCEfG79ktXT09ENzW3UHPoJFv2n2gLh7U7jnB6R+tX5xuye9t0sls3URCISLcwm4wM7m1jcG8bhRe2vuZubKL6gKvtzmFz7dfnG4a1G1LKSNZ8QyAoCEQkaKwWMxf3c3BxP0fba1+db/jH54d47dR8Q9yp+YYhmm/wKwWBiISUs803nA6GLXVOXtlYy+Lm1kElzTd0nYJAREJa+/mGa9rNN2w75G4Lhq/ON3zv9HxDHzsjBvaib7xZ50J3QP9mRCTsmE1Gsnvbye5t5+avzDdsqXPyyQEnm2pP8Pan9fDOdqB1MjorxUpWqo2sFBuDU630tsdqWAkFgYhEiG+abzjkbmSf28uGHYf57KCbz+pdvLvtcNudQ2KcuS0cBqVYyUqxkZGcQIzJGJQegkVBICIRq5fVwvnfc3BhqrXttZONzWw75Oazgy4+r28Nh6Uf1eFpagHAbDSQmZzQeueQamsNihQb9rjI/XEZuZ2JiHyDBIuJnL6J5PRNbHutucXHnqMNfFbv4tNTdw5rdxzhzS0H2v5M38TYtmGlrNTWu4jzImRoSUEgIlHPZDQwIDmBAckJXJ395euH3I18dtDV+k99611E+6Ele6y5NRROh0OYDi0pCEREzqKX1UKvjJ6MzejZ9lqDt5lt9W4+r/8yHF7dVMcXXxlaGnRqWGnwqfmHxLjQXdLq9yDwer3Mnj2bffv20djYSHFxMeeffz4zZ87EYDAwaNAg5syZg9FopKKigvLycsxmM8XFxUyYMMHf5YiI+FV8jIkL+iZywVeHlo41nHHn8P7Oo/yt3dBSn8TYM+4cslJt9EkMjaElvwfBG2+8gcPh4PHHH+fo0aPcdNNNZGdnU1JSwqhRoygtLWXlypXk5uZSVlbG0qVL8Xg8FBUVMW7cOCwWHXQhIuHFZDQwoGcCA3p+fWjp83pX64qlgy4+q3dRWfPl0JIt1tQWCqdXL2UGYWjJ70FwzTXXUFBQ0PZ7k8nEli1bGDlyJAD5+fmsWbMGo9FIXl4eFosFi8VCeno61dXV5OTk+LskEZGg6GW10MvakzEDzhxaqjnkbnf34Oa1rwwtZZxetdRNQ0t+DwKrtXWZlsvl4t5776WkpIR58+a13f5YrVacTiculwu73X7G+1wu17de32Qy4HAkdKo2k8nY6feGGvUSeiKlD1AvgeQA+qTYGT/ky9eaW3zsPnKSrXUn2Lrfyda6E6zbfeyMoaV+PeJ5buoIBvayfu2aXRWQyeK6ujruueceioqKuO6663j88cfbvuZ2u0lMTMRms+F2u894vX0wnE1zs49jx052qi6HI6HT7w016iX0REofoF6CoYfZwNh+SYztl9T22uF2Q0u1J74g3mzsdC8pKWf/+er3IDh06BB33HEHpaWljBkzBoChQ4dSVVXFqFGjqKysZPTo0eTk5DB//nw8Hg+NjY3U1NSQlZXl73JERMJWstVCsrUno08NLTkc8QEJNb8HwYIFCzhx4gTPPPMMzzzzDAC/+c1veOSRR3jiiSfIzMykoKAAk8nElClTKCoqwufzMX36dGJjY/1djoiIfAuDz+fzffsfCx1eb7OGhlAvoShS+gD1Eqq60ktHQ0Phtf1NRET8TkEgIhLlFAQiIlFOQSAiEuUUBCIiUU5BICIS5cJu+aiIiPiX7ghERKKcgkBEJMopCEREopyCQEQkyikIRESinIJARCTKKQhERKJcQE4oCzVer5fZs2ezb98+GhsbKS4u5oorrgh2WZ3S3NzMAw88wI4dOzCZTMydO5f09PRgl9Vphw8fprCwkOeff56BAwcGu5xOu/HGG9tO2EtLS2Pu3LlBrqjzFi5cyD/+8Q+8Xi+TJ0/m1ltvDXZJnbJs2TJeffVVADweD1u3bmXNmjUkJiYGubLvxuv1MnPmTPbt24fRaOThhx/2+/8rUREEb7zxBg6Hg8cff5yjR49y0003hW0QrFq1CoDy8nKqqqqYO3cu//Vf/xXkqjrH6/VSWlpKXFxcsEvpEo/HA0BZWVmQK+m6qqoqPvzwQ15++WUaGhp4/vnng11SpxUWFlJYWAjAb3/7W26++eawCwGAd999l6amJsrLy1mzZg3z58/n6aef9uv3iIqhoWuuuYZf/vKXbb83mUxBrKZrrrzySh5++GEAamtr6dWrV5Ar6rx58+Zx2223kZqaGuxSuqS6upqGhgbuuOMOpk6dysaNG4NdUqe99957ZGVlcc899zBt2jQuv/zyYJfUZZs3b2bbtm1MmjQp2KV0SkZGBs3NzbS0tOByuTCb/f/396i4I7BarQC4XC7uvfdeSkpKgltQF5nNZmbMmMGKFSt46qmngl1OpyxbtoyePXty6aWX8uyzzwa7nC6Ji4vjzjvv5NZbb2Xnzp3cddddvPXWWwH5HzbQjh49Sm1tLQsWLGDv3r0UFxfz1ltvYTAYgl1apy1cuJB77rkn2GV0WkJCAvv27eP73/8+R48eZcGCBX7/HlFxRwBQV1fH1KlTueGGG7juuuuCXU6XzZs3j+XLl/Pggw9y8mT4HcO3dOlS1q5dy5QpU9i6dSszZsygvr4+2GV1SkZGBtdffz0Gg4GMjAwcDkfY9uJwOBg/fjwWi4XMzExiY2M5cuRIsMvqtBMnTrB9+3ZGjx4d7FI67cUXX2T8+PEsX76c119/nZkzZ7YNR/pLVATBoUOHuOOOO7j//vu55ZZbgl1Ol7z22mssXLgQgPj4eAwGQ1gOdf3lL3/hpZdeoqysjCFDhjBv3jxSUlKCXVanvPLKKzz22GMAHDhwAJfLFba9XHzxxaxevRqfz8eBAwdoaGjA4XAEu6xOW7duHWPHjg12GV2SmJjYthAhKSmJpqYmmpub/fo9wu/etRMWLFjAiRMneOaZZ3jmmWcAeO6558JykvLqq69m1qxZ/OhHP6KpqYnZs2cTGxsb7LKi2i233MKsWbOYPHkyBoOBRx99NCyHhQAmTJjAunXruOWWW/D5fJSWloblXzRO27FjB2lpacEuo0t+8pOfMHv2bIqKivB6vUyfPp2EhAS/fg89hlpEJMpFxdCQiIicnYJARCTKKQhERKKcgkBEJMopCEREopyCQKSLqqqqmD59etvv33rrLX74wx9SW1sbxKpEzl14LnYWCVF/+9vfWLRoES+++GJYPwdKoouCQMRPXnvtNV566SVeeOEFkpKSgl2OyDlTEIj4wb/+9S8OHDjA8ePH/b79XyTQNEcg4gcpKSm88MIL3H777dx///20tLQEuySRc6YgEPGD/v37Exsby49//GNiYmLC9rAgiU4KAhE/e/TRR1myZAnvv/9+sEsROSd66JyISJTTHYGISJRTEIiIRDkFgYhIlFMQiIhEOQWBiEiUUxCIiEQ5BYGISJT7/w93g4FK2BU3AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"sns.lineplot(x=clusters, y=SSE)\n",
"plt.xlabel('K')\n",
"plt.ylabel('SSE')"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "714adb7d",
"metadata": {},
"outputs": [],
"source": [
"# 计算曲率\n",
"x_t = np.gradient(clusters)\n",
"y_t = np.gradient(SSE)\n",
"\n",
"vel = np.array([[x_t[i], y_t[i]] for i in range(x_t.size)])\n",
"\n",
"speed = np.sqrt(x_t * x_t + y_t * y_t)\n",
"\n",
"tangent = np.array([1 / speed] * 2).transpose() * vel\n",
"\n",
"tangent_x = tangent[:, 0]\n",
"tangent_y = tangent[:, 1]\n",
"\n",
"d_tangent_x = np.gradient(tangent_x)\n",
"d_tangent_y = np.gradient(tangent_y)\n",
"\n",
"dT_dt = np.array([[d_tangent_x[i], d_tangent_y[i]] for i in range(d_tangent_x.size)])\n",
"\n",
"length_dT_dt = np.sqrt(d_tangent_x * d_tangent_x + d_tangent_y * d_tangent_y)\n",
"\n",
"normal = np.array([1 / length_dT_dt] * 2).transpose() * dT_dt\n",
"\n",
"d2s_dt2 = np.gradient(speed)\n",
"d2x_dt2 = np.gradient(x_t)\n",
"d2y_dt2 = np.gradient(y_t)\n",
"\n",
"curvature = np.abs(d2x_dt2 * y_t - x_t * d2y_dt2) / (x_t * x_t + y_t * y_t) ** 1.5\n",
"t_component = np.array([d2s_dt2] * 2).transpose()\n",
"n_component = np.array([curvature * speed * speed] * 2).transpose()\n",
"\n",
"acceleration = t_component * tangent + n_component * normal"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "eadb907c",
"metadata": {},
"outputs": [],
"source": [
"normalization_acceleration = acceleration\n",
"normalization_acceleration[:, 1] = (acceleration[:, 1] - np.min(acceleration[:, 1]))/(np.max(acceleration[:, 1]) - np.min(acceleration[:,1]))\n",
"normalization_curvature = normalization_acceleration[:, 1]"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "b2d383e8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0, 0.5, 'normalization curvature')"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"sns.lineplot(x=clusters, y=normalization_curvature)\n",
"plt.xlabel('K')\n",
"plt.ylabel('normalization curvature')"
]
},
{
"cell_type": "markdown",
"id": "08948ffb",
"metadata": {},
"source": [
"$$\n",
"S = \\frac{b - a}{\\max{(a, b)}}\n",
"$$\n",
"$S$样本点$X_i$的轮廓系数,$a$是$X_i$与同簇的其他样本的平均距离,称为凝聚度,$b$是$X_i$与最近簇中所有样本的平均距离,称为分离度。\n",
"$$\n",
"C_j = \\arg{\\min_{C_i}\\frac{1}{n}\\sum_{p\\in{C_i}}|p-X_i|^2}\n",
"$$\n",
"$C_j$是最近簇其中p是某个簇$C_k$中的样本。事实上,简单点讲,就是用$X_i$到某个簇所有样本平均距离作为衡量该点到该簇的距离后,选择离$X_i$最近的一个簇作为最近簇。求出所有样本的轮廓系数后再求平均值就得到了平均轮廓系数。平均轮廓系数的取值范围为[-1,1]且簇内样本的距离越近簇间样本距离越远平均轮廓系数越大聚类效果越好。那么很自然地平均轮廓系数最大的k便是最佳聚类数。"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "321eceaf",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0.3926532652562246, 0.4165845111425452, 0.45642014396553005, 0.4581536763935582, 0.46087941918329456, 0.4601172904178992, 0.4810293417489168]\n"
]
}
],
"source": [
"# 轮廓系数来确定最优K值数据量大时效率不高\n",
"SCORE = []\n",
"for i in clusters:\n",
" kmeans = KMeans(n_clusters=i)\n",
" result = kmeans.fit_predict(normalization_rfm)\n",
" score = silhouette_score(normalization_rfm, result)\n",
" SCORE.append(score)\n",
"print(SCORE)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "dbf44f9e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0, 0.5, 'SCORE')"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYQAAAEECAYAAAAoDUMLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAmRklEQVR4nO3de1xUZf4H8M8wwwyXEcYLKqYioFjeMsvKklUzM00t8QK6G7m2sZlmmVZm4U/TRc3WzEhRd81ftgW/FUrJxHLzSmXmgoopKBcvgIDIxYEZ5nLO7w9wklTUgZkzl8/79fLFzJlzmO8jcD7n8szzyERRFEFERG7PQ+oCiIjIMTAQiIgIAAOBiIgaMBCIiAgAA4GIiBoopC6gOQRBgNlsXScpuVxm9baOxlXa4irtANgWR+UqbWluOzw95Tdc7tSBYDaLqKystWpbjcbH6m0djau0xVXaAbAtjspV2tLcdgQEtLrhcl4yIiIiAAwEIiJqwEAgIiIADAQiImrAQCAiIgAMBCIiasBAICIiAAwEIiKncrnWgG1Hi2CLmQts8sE0QRCwaNEiZGdnQ6lUYunSpQgKCrpuvdjYWPj7+2PevHkwGo2YP38+CgsL4eHhgSVLliA0NNQW5REROaXCKh1e3nocl2uNSHvxYXjd5BPH1rLJGcLu3bthMBiQlJSEuXPnYvny5detk5iYiJycHMvzffv2wWQyITExETNnzsTq1attURoRkVM6c6kGf/niKKr0Jnzy3AMtHgaAjQLhyJEjCA8PBwD0798fWVlZjV7PyMjA0aNHERkZaVkWHBwMs9kMQRCg1WqhUDj1qBpERC3mWFE1/pp0FACwPvJe3Ne1tU3exyZ7Xa1WC7VabXkul8thMpmgUChQWlqK+Ph4xMfHY+fOnZZ1fHx8UFhYiFGjRqGiogIJCQm3fB+5XAaNxseqGuVyD6u3dTSu0hZXaQfAtjgqZ2zL/tNlmLX1ONq3UuGTaQ+gS2sfm7XDJoGgVqtRU1NjeS4IguWIPy0tDRUVFYiJiUFZWRn0ej1CQkKQnZ2NwYMHY+7cuSguLsZzzz2H1NRUqFSqm74PB7er5yptcZV2AGyLo3K2tnx7qhQLd2YjtK0P1kzoi1YyoLKy1rkGtxswYAD2798PAMjMzERYWJjltejoaKSkpGDLli2IiYnBmDFjEBERAT8/P7RqVV+kv78/TCYTzGazLcojInJ4/84swjs7TqFfJz+sj7wXbX2VNn9Pm5whjBgxAunp6YiKioIoioiLi0Nqaipqa2sb3Te41rRp07BgwQJMnToVRqMRc+bMgY+Pc53aERE1lyiK+MdP57Dhh7MID2mDuDH32OQG8o3IRFt0ZrUTo9HMS0Zwnba4SjsAtsVROXpbBFHEqj25SMoowlO92uOdkT2h8JBdt56tLhmxKw8RkQMwmQUs3pWDtJOlmHr/XXhlSAg8ZNeHgS0xEIiIJKY3mjE/9STS8y/jpcHdMO3BLpDZOQwABgIRkaSu6E2Y82UWjhVV460RPRDRL1CyWhgIREQSuaStw+yULOSX1yJuzD14vGeApPUwEIiIJHChUodZW4/jcq0Bq8f3wUPdbPPp4zvBQCAisrPTZVq8nJwFk1nAukn90DvQT+qSAHD4ayIiu8q8UIWYpKOQy4ANUfc6TBgAPEMgIrKb9LzLeDP1V3RopUL8xL4I9POSuqRGGAhERHaw82QJFqfloEc7X3w4oQ/a+Nh+KIo7xUAgIrKxpP8W4v09ubi/iz/ef7o31CrH3PU6ZlVERC5AFEVs+OEs/vHTOQzt3hZLn7oHKoXj3rplIBAR2YAgilj5nzPYerQYY3t3wIInwm44LpEjYSAQEbUwo1nAop3Z+Da7DM8+0Bkv/yFYkqEo7hQDgYioBemMZry5/Vf8WFCBl8ODEf1gF6lLum0MBCKiFlKlM2LOlydw4mI13h7RA89IOC6RNRgIREQtoExbh5eTj+NchQ7LxvbCYz3aSV3SHWMgEBE10/kKHWZtPYZKnQkfRvTBwK7Sj0tkDQYCEVEzZJdqMTv5OAQRWDe5H3p1vPFsZM6AgUBEZKX/XqjEa1+egFqlQPyEvujW1rnngWcgEBFZYX9uORZ8fRKBfip8NKEvOjrYuETWYCAQEd2hHSdKsGRXNnp2aIUPx/eBxsdT6pJaBAOBiOgOfH7kAj7Ym4eBXTVY+XQv+CpdZzfqOi0hIrIhURSRkF6ATYfOY1iPdlg6+m4oHXhcImswEIiIbsEsiHjvP2eQcqwYz/TtiPmP94DcwcclsgYDgYioCQaTgP/ZeQq7cy7huQe7YObgbk4xLpE1GAhERDdRazDjje0ncOhsJV4ZEoI/PdBZ6pJsioFARHQDlToj5nyZhZMXr2DhyDCM7dNR6pJsjoFARPQ7JVfq8PLW4yis0mHFuF4Y0t35xiWyBgOBiOgaZy/XYtbW47hSZ8KaCX1xfxeN1CXZDQOBiKjBqZIrmJ2cBQBImNwPd3dw3nGJrMFAICICcOR8JeZ+dQKtVArET+yLoDbOPS6RNRgIROT29p6+hLd3nMRdGm98NKEvOrRSSV2SJBgIROTWtmddxN++zUGvjq3wwfg+0Hi7xrhE1mAgEJHb+uyXC/hwXx4eCtLgvXG94aOUS12SpBgIROR2RFHExwcL8L8/n8fjYQFYPKqny41LZA0GAhG5FbMgYtnu09h2/CIi+gXijeHdXXJcImswEIiokTqTgIvVelysrsPFK3p4eCpgNpig8vSASiGHSu4BlcIDSkX912v/KeUe8FJ4QCF3zKPtOpOAt74+iT2nL2H6w13x4iNBLjsukTVsEgiCIGDRokXIzs6GUqnE0qVLERQUdN16sbGx8Pf3x7x58wAA69evx/fffw+j0YgpU6Zg0qRJtiiPyG2JoogrdSYUV9fhYrW+4Wv9jv/qssu1xma/j1yGhsCQQymXwctTbgmMq2HidU2INF4mbxw2vwsgL8vjhu+tkEPlWf99mjrSrzGY8MqWI/ghrxxzhoZg6v2uPS6RNWwSCLt374bBYEBSUhIyMzOxfPlyrFu3rtE6iYmJyMnJwcCBAwEAhw4dQkZGBr744gvodDps2rTJFqURuTSzIKK8xoDihiP84mo9Ll6p++1xdR1qjeZG26gUHujYSoVAPy/0CG2LQL/6xx0alnVop0ZZuRZ1JsHyz2AWoDcJMFiWmVFnEhu+1r9+7fp1165rFlCtN6HMZL5m+9/+ic1ov8JDdt0Zy9XH5bVGlFypw+JRPTG6V4fm/Ue7KJsEwpEjRxAeHg4A6N+/P7Kyshq9npGRgaNHjyIyMhJ5eXkAgIMHDyIsLAwzZ86EVqvFG2+8ccv3kctl0Gis+/CIXO5h9baOxlXa4irtAGzXljqjGcXVehRW6lBUqUdRpQ6FVfWPCyt1KKnWw2huvEvVeHuik8YbIQFqDO4RgLs0Xuik8cZdGm908vdCG19lk5dN5HIPtPVVtnhbbkQURRjNvwWL3miG3nht6Py2zGASoL9mWZ2xfh391XCxbFu/zNfLE+8+3QdDejj/uES2+v2ySSBotVqo1WrLc7lcDpPJBIVCgdLSUsTHxyM+Ph47d+60rFNRUYGioiIkJCTgwoULmDFjBtLS0pr8RTWbRVRW1lpVo0bjY/W2jsZV2uIq7QCsb8sVvQnF1b9dvqk/uq9/XnyDyzkeMqCdrxKBfl7o3UGN4T3aIdBPhY5+Xpaj/ia7UprMqKrS2aQtzaUAoJYBaqUHoPRAS+yuXOV3rLntCAi48ZAcNgkEtVqNmpoay3NBEKBQ1L9VWloaKioqEBMTg7KyMuj1eoSEhECj0SAkJARKpRIhISFQqVS4fPky2rZta4sSiexOEK9ezqmz3LS9eknn6uWcGsP1l3PqL92oEB7SFh0bLud09FOho58KHdQqh72BS87HJoEwYMAA7NmzB6NHj0ZmZibCwsIsr0VHRyM6OhoAkJKSgry8PERERGDPnj349NNP8ec//xmlpaXQ6XTQaDS2KI+oRYmiiBqDGZU6I6p0RlTqTKgVLyO/pLrRzduSK3UwCY0v5/h5KdCxlQqd/b3xQBcNOvp5NTrCb+PjyV4wZDc2CYQRI0YgPT0dUVFREEURcXFxSE1NRW1tLSIjI2+4zbBhw3D48GFMnDgRoihi4cKFkMvd+1ODZH+CKEJbZ0KlztSwczeiSm/83XMTKq8+bnhuFq6/FSoDEKBWoqOfF/oEtsLwsADLDdurR/i+Svb8JschE0WxOTf1JWU0mnkPAa7TlpZuhyCKqNZfvyO/ehRfZdnZG1Glq3+tWm+E+SZ/EXIPGTTenvD3UtR/9faExlsBfy9PaLw9G5bVv9a1gx+8RQGeLnA5x1V+vwDXaYtT3UMgamlmQcSVa4/Mf7cj//1RfKXOiCt1JtzgwB0A4CmXWXbk/t4KhLTzsezs/S07d09ornnuq5Tf9uUbV9nxkHthIJBDMJoF/OvQOZy5WH3N5RgTqvT1R/TVetNN+6cr5TLLDtzf2xM9AtSWI/WbHcX7eN7+zp3IXTAQyCF8evg8EtLPQqXwaHRZpqOfutHzay/LXD1y91J4cOdO1AIYCCS5Mm0dNh86j5G9OmDpqJ5Sl0Pktpz/jhc5vY8PFsAsinhjJMOASEoMBJLUrxevYMeJEkwZ0Bld3XAOWyJHwkAgyYiiiA/25qKNjyf+/FAXqcshcnsMBJLMf3IuIbOwGjMe7Qa1ireziKTGQCBJ1JkErNmfhx4Bvhjbp6PU5RARGAgkkc+PXEBxdR1eGxrK6QuJHAQDgezuUo0Bmw+dx9DubfFAV43U5RBRAwYC2V3CwQIYzAJm/yFE6lKI6BoMBLKr7BIttmddROR9d6FLa2+pyyGiazAQyG5EUcSqvbnw9/bE8w93lbocIvodBgLZzZ4z5fjvhSq8+GgQWnmxmymRo2EgkF0YTALW7MtDaDsfPN03UOpyiOgGGAhkF0kZhSis0mPOkFAo2M2UyCExEMjmymsM+OdP5zA4pA0e6tZa6nKI6CYYCGRz638ogN4k4JUh7GZK5MgYCGRTp8u02Hb8Iib374RuHM2UyKExEMhm6kczzUMrlQJ/GcRupkSOjoFANrM/9zIOn6tEzCNB8PPylLocIroFBgLZhNEs4MN9uQhu44OIfuxmSuQMGAhkE//OLML5Sj1eHRoChZy/ZkTOgH+p1OIqa43Y+ONZDOrWGo8Et5G6HCK6TQwEanHrfyiAzmDGq0PZzZTImTAQqEXlXqpByrFiTLi3E0La+kpdDhHdAQYCtRhRFLF6bx58lQq88EiQ1OUQ0R1iIFCL+SG/Aj+drcBfBnWFxpvdTImcDQOBWoTJLOCDvbno2tobk/p3krocIrICA4FaxNajxThbocOrQ0LgyW6mRE6Jf7nUbFW6+m6mDwVpMDiE3UyJnFWTgZCcnGx5fPr0acvj+Ph421VETmfjj2ehrTPh1aGhkMk41wGRs2oyELZt22Z5vGTJEsvjn3/+2XYVkVPJL6/F1swijO8XiO7t2M2UyJk1GQiiKN7yMbm3D/flwctTjr+ymymR02syEK49/b/ZY3JfPxZcRnr+ZfxlUBBa+yilLoeImqnJQKisrER6ejoOHDiAqqoqHDx40PK4KYIgYOHChYiMjMSzzz6Ls2fP3nC92NhYvP/++42WlZeXY8iQIcjNzb3DppA9mYT6uQ46a7wwmd1MiVyCoqkXe/fuja+//hoA0KtXL+zYscPyuCm7d++GwWBAUlISMjMzsXz5cqxbt67ROomJicjJycHAgQMty4xGIxYuXAgvLy+rGkP28+WxYuSX12LluF5QKthZjcgVNBkIy5Ytu+Hy7OzsJr/pkSNHEB4eDgDo378/srKyGr2ekZGBo0ePIjIyEnl5eZblK1asQFRUFDZs2HBbxZM0qvVGrE8vwANd/DGke1upyyGiFtJkIBw4cADvvfce/P39sWzZMgQGBmLVqlX45ptvsHfv3ptup9VqoVarLc/lcjlMJhMUCgVKS0sRHx+P+Ph47Ny507JOSkoK2rRpg/Dw8NsOBLlcBo3Gunl65XIPq7d1NPZuy7qdp1BdZ0Ls2N5o3brlehbxZ+KY2BbHY6t2NBkIK1euxJo1a1BYWIi///3vKC8vR2BgYKPuqDeiVqtRU1NjeS4IAhSK+rdKS0tDRUUFYmJiUFZWBr1ej5CQECQnJ0Mmk+HHH3/EyZMn8eabb2LdunUICAi46fuYzSIqK2vvpL0WGo2P1ds6Gnu25ezlWvzvT2cxrk9HdPJWtOj78mfimNgWx9PcdgQEtLrh8iYDwc/PD8HBwQgODsbbb7+NmTNnYvLkybd8swEDBmDPnj0YPXo0MjMzERYWZnktOjoa0dHRAOrPCvLy8hAREYGIiAjLOs8++ywWLVrUZBiQNNbsz4eXwgMzHu0mdSlE1MKaDAQPj99uFgYGBt5WGADAiBEjkJ6ejqioKIiiiLi4OKSmpqK2thaRkZHNq5gk8/PZCuzPLces8GC09WU3UyJX02Qg6HQ6FBQUQBAECIKAgoICy4fSgoODb7qdh4cH3n333UbLQkNDr1vv2rOCa23ZsuWWhZN9mRu6mXbyUyFqwF1Sl0NENtBkIHh5eSE2NhYAoFKpLI9lMhk+/fRT21dHDmNb1kWcuVSD5WPvgYrdTIlcUpOBwCN1AgBtnQkJBwtw311+eKxHO6nLISIbaTIQAGDTpk1ISkqCTqeDp6cnpk6diueff94etZGD2PTTOVTqjJgzrA+HLSFyYU2e+2/evBn5+flITk7G/v37sW3bNuTm5uIf//iHveojiV2o1CExoxBP9e6AezrcuKsaEbmGJgNh165dWLx4seVDZmq1GosXL8Z3331nl+JIemv250PhIcNLg7tJXQoR2ViTgeDp6dmo6+nVZVc/ZEau7cj5Suw5fQnTHuyKALVK6nKIyMZuOfx1eXl5o2WXLl26LiTI9ZgFEav25KJjKxWm3s9upkTuoMk9+4wZM/DCCy/g22+/xalTp7B792789a9/xYsvvmiv+kgiO06UIKesBi//IRhennKpyyEiO2jy2s/DDz+MFStWIDExEVu3bkXHjh2xZMmSWw5/Tc6txmDCxwfz0TfQDyN6cvgQIndxy5sBAQEBlg+k8XKRe9h86Dwu1xqx6pne7GZK5Eaa3Lv//PPPGD9+vGWGtOzsbEyYMAG//PKLXYoj+yuq0uPzIxcwuld79A70k7ocIrKjJgNh9erV2LJlC/z9/QEAjz76KDZt2oRVq1bZpTiyv4/250Mmk+GlwTcfq4qIXFOTgSCXy9G5c+dGy4KDg3nZyEVlXqjC7pwyPDewCzq0YjdTInfT5J5dFEUIgtBomdlshtFotGlRZH+CKGLV3ly0Vyvx7MDOt96AiFxOk4Ewbtw4vPbaazh16hS0Wi3OnDmDefPmYdSoUfaqj+zkm19LcLJEi1nsZkrktprsZTR58mSo1WrExcWhrKwMnTp1wtixY/HMM8/YqTyyh1qDGWsPFqB3x1YYeXd7qcshIok0GQgnTpzAhg0b8H//93/Yu3cvFi1ahAsXLsDPzw+PPfaYvWokG/v08HmUaQ1YPrYXPNjNlMhtNXnJ6IMPPsDy5cuhVCqxevVqbNy4EcnJydiwYYO96iMbu1itx2e/XMDIuwPQrxO7mRK5sybPEERRxN13342SkhLodDr07t0bANjLyIXEH8gHAMwKZzdTInfX5J79ag+jAwcOYNCgQQAAg8GAmpoa21dGNnesqBq7TpXhjw90Rkc/L6nLISKJNXmGMGjQIERFReHixYtYt24dzp07h0WLFmH06NH2qo9sRBBFfLA3F+18lXhuYBepyyEiB9BkIMTExGD48OFo06YNWrdujXPnzmHKlCkYMWKEveojG9l1qhRZxVfwP0+GwUfJbqZEdBuD24WGhloed+3aFV27drVpQWR7OqMZ8fvzcU8HNUb36iB1OUTkIHh32A19dvgCSrUGzBkaym6mRGTBQHAzJVfq8Onh83g8rB3u6+wvdTlE5EAYCG5m7cF8CKKIWX9gN1MiaoyB4EZOFFfjm19LMfX+zrjL31vqcojIwTAQ3IQoili1Nw9tfDwx7SF2MyWi6zEQ3MR32WU4VlSNlwZ3g6/ylp3LiMgNMRDcgN5oxkf78xEW4IsxvTtKXQ4ROSgGghv4/EghLl6pw2vDQiH3YDdTIroxBoKLK9PWYfPP5zC0e1vc30UjdTlE5MAYCC5u3cECGM0iXhkSInUpROTgGAgu7GTJFXx9ogRTBtyFzhp2MyWipjEQXJQoivhgTy403p6Y/jDHnyKiW2MguKjvT19CRmE1Xnw0CGoVu5kS0a0xEFxQnUnAmv356N7OF+P6BkpdDhE5CZscOgqCgEWLFiE7OxtKpRJLly5FUFDQdevFxsbC398f8+bNg9FoxIIFC1BYWAiDwYAZM2Zg+PDhtijP5SX+txBFVXp8PLEvFOxmSkS3ySZnCLt374bBYEBSUhLmzp2L5cuXX7dOYmIicnJyLM+3b98OjUaDzz//HBs3bsSSJUtsUZrLu1RjwCeHzuEPoW3xYFBrqcshIidikzOEI0eOIDw8HADQv39/ZGVlNXo9IyMDR48eRWRkJPLy8gAATz75JEaOHGlZRy7nLF7WSEgvgN4kYDZHMyWiO2STQNBqtVCr1ZbncrkcJpMJCoUCpaWliI+PR3x8PHbu3GlZx9fX17Lt7Nmz8eqrr97yfeRyGTQaH6tqlMs9rN7W0Vxty6/F1diedRHTBgXh3pB2Upd1x1zxZ+IK2BbHY6t22CQQ1Go1ampqLM8FQYBCUf9WaWlpqKioQExMDMrKyqDX6xESEoKIiAgUFxdj5syZmDp1KsaOHXvL9zGbRVRW1lpVo0bjY/W2jkaj8UFFRQ3eTT0BP5UCf7qvk1O2zdV+JmyL43GVtjS3HQEBrW643CaBMGDAAOzZswejR49GZmYmwsLCLK9FR0cjOjoaAJCSkoK8vDxERETg0qVLmD59OhYuXIhBgwbZoiyXtu9MOY6cr8Ibw7vDz8tT6nKIyAnZJBBGjBiB9PR0REVFQRRFxMXFITU1FbW1tYiMjLzhNgkJCaiursbatWuxdu1aAMDGjRvh5eVlixJdSp1JwIf78xDc1gfj+7GbKRFZRyaKoih1EdYyGs28ZAQg+UQJlqdlY82EPhjUrY3U5VjNlX4mbItjcpW22OqSET+Y5uQqag2I35OLR4PbOHUYEJH0GAhObv0PZ6EzmjmaKRE1GwPBiW3Puojko8X444NdEdzW+bvSEZG0GAhOand2Gf72bQ4eCtLgjZE9pS6HiFwAA8EJpeddxjvfnELfQD+sfLo3VAr+GImo+bgncTJHzlfizdRf0aOdL1ZH9IG3J4f4IKKWwUBwIlnF1XjtyxPo5O+Fjyb05TwHRNSiGAhO4nSZFrOTs9DaxxMfT+wLjQ8/jUxELYuB4AQKLtdi1tbj8Pb0wNpJ/RCgVkldEhG5IAaCgyuu1mPmv49BFIGPJ/ZDJ38O5UFEtsGL0A7skrYOL/37GHRGAQmT+6EbP2tARDbEMwQHVVlrxMytx1FeY8CHEX0Q1l59642IiJqBgeCAtHUmzE45jguVOvz9md7o28lP6pKIyA3wkpGD0RvNeO3LLOSU1WDluF4Y2JXzIhORffAMwYEYTAJe3/YrjhZV491RPREe2lbqkojIjTAQHIRJEPH2jpP46WwF3h4Rhifubi91SUTkZhgIDkAQRSzZlY29Z8rx2rBQjOvbUeqSiMgNMRAkJooi3vvPGXzzaylefDQIUwbcJXVJROSmGAgSEkUR8QfykXy0GNEDO2P6Q12lLomI3BgDQUKfHDqPTw9fwIR7AzErPBgymUzqkojIjTEQJPLFfwuxLr0Ao3u1xxvDuzMMiEhyDAQJbD9+Eav25GJo97aIHdkTHgwDInIADAQ7+y67DH/7LgcPd2uNvz11DxQeDAMicgwMBDs6kFuO2G9O4d5Oflg5rheUnPqSiBwI90h28su5SsxP/RVhAb5YNb4PvDj1JRE5GAaCHRwvqsZrX2Whs8Ybazj1JRE5KAaCjeWUavFKShba+irrp7705tSXROSYGAg29PupL9tx6ksicmAMBBspqqqf+lImA9ZO6odAP059SUSOjRezbaDsd1NfBrXh1JdE5Ph4htDCrk59WVFrxJoJnPqSiJwHzxBa0NWpL4uq9Pgwog/6BHLqSyJyHgyEFqIzmjGnYerL95/uhfu7aKQuiYjojvCSUQuon/ryBI4VVWPp6LsxOIRTXxKR82EgNNPVqS8Pna3E20+E4fGeAVKXRERkFQZCMwiiiHfT6qe+nDcsFOP6cOpLInJeDAQrXZ36cufJUrw0uBsiOfUlETk5m9xUFgQBixYtQnZ2NpRKJZYuXYqgoKDr1ouNjYW/vz/mzZt329s4AlEU8dH+q1NfdsG0B7tIXRIRUbPZ5Axh9+7dMBgMSEpKwty5c7F8+fLr1klMTEROTs4dbeMoNh06hy2/XMCk/p0wK7wbZzsjIpdgkzOEI0eOIDw8HADQv39/ZGVlNXo9IyMDR48eRWRkJPLy8m5rmxuRy2XQaKz7FLBc7mHVtp/8UICE9LMY378Tlo7vCw8HmODG2rY4GldpB8C2OCpXaYut2mGTQNBqtVCrf/uErlwuh8lkgkKhQGlpKeLj4xEfH4+dO3fe1jY3YzaLqKystapGjcbnjrfddrwYcd+exmM92uGNYaGortZZ9d4tzZq2OCJXaQfAtjgqV2lLc9sRENDqhsttEghqtRo1NTWW54IgWHbsaWlpqKioQExMDMrKyqDX6xESEtLkNo7g21Ol+Nu3pzGoW2ssfepuTn1JRC7HJvcQBgwYgP379wMAMjMzERYWZnktOjoaKSkp2LJlC2JiYjBmzBhEREQ0uY3U9ueWY+HObPTv7I/3xvWCp5yds4jI9djkEHzEiBFIT09HVFQURFFEXFwcUlNTUVtbi8jIyNvexhEcPleBt1J/Rc/2aqx6pjenviQilyUTRVGUughrGY1mm95DOFZUjVlbj6GTvxcSJt/rsLOd8bqo42FbHJOrtMVW9xB47eMmsku1eCXlONr5KhE/sZ/DhgERUUthINxAQXktXt56HL5KBT6e1A/tfJVSl0REZHMMhN8prNJh5lZOfUlE7sdx+nU6gDJtHWb++zj0JgHrJ9+Lrq29pS6JiMhueIbQoNHUlxF90D3AV+qSiIjsimcIqJ/68uXk36a+7M2pL4nIDbn9GYLOaMarKVk4c6kGK8Zx6ksicl9uHQh1DVNfHi+uxtKn7sajwW2kLomISDJuGwhGs4C3v66f+jJ2ZBiGh3HqSyJyb24ZCIIoYn7KcezLLcfrj3XHmN6c+pKIyC0D4dOfz2P7sWLMHNwNk+/rJHU5REQOwS17GXUP8MXSp3tjZPe2UpdCROQw3DIQBoe0dZlBroiIWopbXjIiIqLrMRCIiAgAA4GIiBowEIiICAADgYiIGjAQiIgIAAOBiIgaMBCIiAgAIBNFUZS6CCIikh7PEIiICAADgYiIGjAQiIgIAAOBiIgaMBCIiAgAA4GIiBowEIiICIAbTpBjNBqxYMECFBYWwmAwYMaMGRg+fLjUZd0xs9mMd955B/n5+ZDL5Vi2bBm6du0qdVnNUl5ejoiICGzatAmhoaFSl2O1Z555Bq1atQIAdO7cGcuWLZO4IuutX78e33//PYxGI6ZMmYJJkyZJXdIdS0lJwZdffgkAqKurw8mTJ5Geng4/Pz+JK7tzRqMR8+fPR2FhITw8PLBkyZIW/Vtxu0DYvn07NBoNVq5ciYqKCowfP94pA2HPnj0AgMTERBw6dAjLli3DunXrJK7KekajEQsXLoSXl5fUpTRLXV0dAGDLli0SV9J8hw4dQkZGBr744gvodDps2rRJ6pKsEhERgYiICADA4sWLMWHCBKcMAwDYt28fTCYTEhMTkZ6ejtWrV+Ojjz5qse/vdpeMnnzySbzyyiuW53K5XMJqrPf4449jyZIlAICioiK0a9dO4oqaZ8WKFYiKikL79u2lLqVZTp06BZ1Oh+nTpyM6OhqZmZlSl2S1gwcPIiwsDDNnzsSLL76IoUOHSl1Ssxw/fhxnzpxBZGSk1KVYLTg4GGazGYIgQKvVQqFo2WN6tztD8PX1BQBotVrMnj0br776qrQFNYNCocCbb76J7777DmvWrJG6HKulpKSgTZs2CA8Px4YNG6Qup1m8vLzw/PPPY9KkSSgoKMALL7yAtLS0Fv/DtYeKigoUFRUhISEBFy5cwIwZM5CWlgaZTCZ1aVZZv349Zs6cKXUZzeLj44PCwkKMGjUKFRUVSEhIaNHv73ZnCABQXFyM6OhoPP300xg7dqzU5TTLihUrsGvXLsTGxqK2tlbqcqySnJyMH374Ac8++yxOnjyJN998E2VlZVKXZZXg4GCMGzcOMpkMwcHB0Gg0TtsWjUaDwYMHQ6lUIiQkBCqVCpcvX5a6LKtUV1cjLy8PDz/8sNSlNMvmzZsxePBg7Nq1C9u2bcP8+fMtlylbgtsFwqVLlzB9+nS8/vrrmDhxotTlWO2rr77C+vXrAQDe3t6QyWROe/nrX//6Fz777DNs2bIF99xzD1asWIGAgACpy7LK1q1bsXz5cgBASUkJtFqt07bl/vvvx4EDByCKIkpKSqDT6aDRaKQuyyqHDx/GI488InUZzebn52fpsODv7w+TyQSz2dxi39/5zmObKSEhAdXV1Vi7di3Wrl0LANi4caPT3cx84okn8NZbb+GPf/wjTCYTFixYAJVKJXVZbm/ixIl46623MGXKFMhkMsTFxTnl5SIAGDZsGA4fPoyJEydCFEUsXLjQaQ868vPz0blzZ6nLaLZp06ZhwYIFmDp1KoxGI+bMmQMfH58W+/4c/pqIiAC44SUjIiK6MQYCEREBYCAQEVEDBgIREQFgIBARUQMGAlELOnToEObMmWN5npaWhjFjxqCoqEjCqohuj3N2kCZyAjt27MA///lPbN682enHmiL3wEAgsoGvvvoKn332GT755BP4+/tLXQ7RbWEgELWwX375BSUlJaiqqmrRYQWIbI33EIhaWEBAAD755BM899xzeP311yEIgtQlEd0WBgJRCwsKCoJKpcKf/vQneHp6OvXEReReGAhENhQXF4ekpCT89NNPUpdCdEsc3I6IiADwDIGIiBowEIiICAADgYiIGjAQiIgIAAOBiIgaMBCIiAgAA4GIiBr8PxU4Nf5ALlUAAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"sns.lineplot(x=clusters, y=SCORE)\n",
"plt.xlabel('K')\n",
"plt.ylabel('SCORE')"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "85850690",
"metadata": {},
"outputs": [],
"source": [
"tup_list = []\n",
"for i in range(7):\n",
" item = (clusters[i], normalization_curvature[i] * 0.1 + SCORE[i] * 0.9)\n",
" tup_list.append(item)\n",
"tup_list = sorted(tup_list, key=lambda x: x[1], reverse=True)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "7ce62d18",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"clf_KMeans聚类中心\n",
" [[ 7.54696970e-01 -1.38777878e-17 9.34848485e-02]\n",
" [ 7.45000000e-01 1.47368421e-02 7.53289474e-01]\n",
" [ 1.28099174e-01 8.67361738e-19 9.94031221e-02]\n",
" [ 1.22093023e-01 -1.73472348e-18 7.59222133e-01]]\n"
]
}
],
"source": [
"# 模型训练。得到预测值。\n",
"k = tup_list[0][0]\n",
"k_model = KMeans(n_clusters=k)\n",
"k_model.fit(normalization_rfm)\n",
"print(\"clf_KMeans聚类中心\\n\", k_model.cluster_centers_)"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "e5365af7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"cluster2聚类数量\n",
" 1 1900\n",
"0 1650\n",
"3 1247\n",
"2 1089\n",
"dtype: int64\n"
]
}
],
"source": [
"quantity = pd.Series(k_model.labels_).value_counts()\n",
"print(\"cluster2聚类数量\\n\", quantity)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "592e7328",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"UPDATE `sys_user` SET `persona` = 1 WHERE `account` IN ('1234567', '1951119', '1951122', '1951123', '1951124', '1951125', '1951126', '1951127', '1951128', '1951129', '1951130', '1951131', '1951132', '1951133', '1951134', '1951135', '2051101', '2051102', '2051103', '2051104', '2051105', '2051106', '2051107', '2051108', '2051109', '2051110', '2051111', '2052520')\n"
]
}
],
"source": [
"# 获取聚类之后每个聚类中心的数据\n",
"res0Series = pd.Series(k_model.labels_)\n",
"message = [\"\", \"\", \"据分析,您近期的表现不佳,请注意!\", \"据分析,您近期的表现存在严重问题,请及时整改!\"]\n",
"query_sql = \"SELECT `account` FROM `sys_user`\"\n",
"query_data = pd.read_sql(query_sql, db_engine)\n",
"for i in range(0, k):\n",
" res0 = res0Series[res0Series.values == i]\n",
" temp_list = []\n",
" for account in rfm_df2['account'].iloc[res0.index].values:\n",
" if str(account) in query_data[\"account\"].values:\n",
" temp_list.append(str(account))\n",
" if i >= 2:\n",
" insert_sql = \"INSERT INTO `sys_message` (`account`, `title`, `content`, `create_user`, `create_time`) VALUES ('\" + str(account) + \"', '分析结果提醒', '\" + message[i] + \"', 'admin', '\" + str(time.strftime(\"%Y-%m-%d %H:%M:%S\", time.localtime())) + \"')\"\n",
" db_engine.execute(insert_sql)\n",
" if len(temp_list) > 0:\n",
" update_sql = \"UPDATE `sys_user` SET `persona` = \" + str(i) + \" WHERE `account` IN (\" + str(temp_list).replace(\"[\", \"\").replace(\"]\", \"\") + \")\"\n",
" db_engine.execute(update_sql)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "06dd4a51",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.13"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 5
}