{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用 K 均值算法来分类安然的财务数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "import numpy\n",
    "import matplotlib.pyplot as plt\n",
    "import sys\n",
    "sys.path.append(\"../tools/\")\n",
    "from feature_format import featureFormat, targetFeatureSplit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Draw(pred, features, poi, mark_poi=False, name=\"image.png\", f1_name=\"feature 1\", f2_name=\"feature 2\"):\n",
    "    \"\"\" some plotting code designed to help you visualize your clusters \"\"\"\n",
    "\n",
    "    ### plot each cluster with a different color--add more colors for\n",
    "    ### drawing more than five clusters\n",
    "    colors = [\"b\", \"c\", \"k\", \"m\", \"g\"]\n",
    "    for ii, pp in enumerate(pred):\n",
    "        plt.scatter(features[ii][0], features[ii][1], color = colors[pred[ii]])\n",
    "\n",
    "    ### if you like, place red stars over points that are POIs (just for funsies)\n",
    "    if mark_poi:\n",
    "        for ii, pp in enumerate(pred):\n",
    "            if poi[ii]:\n",
    "                plt.scatter(features[ii][0], features[ii][1], color=\"r\", marker=\"*\")\n",
    "    plt.xlabel(f1_name)\n",
    "    plt.ylabel(f2_name)\n",
    "    plt.savefig(name,dpi=150)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "移除 TOTAL 项目，此处其属于异常值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Removed the outlier.\n"
     ]
    }
   ],
   "source": [
    "### load in the dict of dicts containing all the data on each person in the dataset\n",
    "data_dict = pickle.load( open(\"../final_project/final_project_dataset.pkl\", \"rb\") )\n",
    "\n",
    "### there's an outlier--remove it! \n",
    "data_dict.pop(\"TOTAL\")\n",
    "print(\"Removed the outlier.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The max value of exercised_stock_options is  LAY KENNETH L 34348384\n",
      "The min value of exercised_stock_options is  BELFER ROBERT 3285\n",
      "The max value of salary is  SKILLING JEFFREY K 1111258\n",
      "The min value of salary is  BANNANTINE JAMES M 477\n"
     ]
    }
   ],
   "source": [
    "# 定义了一个函数来直接给出数据集中某项的最大值和最小值\n",
    "def min_and_max(obj):\n",
    "    obj_want_to_check = obj\n",
    "    max_v = 0\n",
    "    max_name = None\n",
    "    for v in data_dict.keys():\n",
    "        if data_dict[v][obj_want_to_check] != \"NaN\":\n",
    "            if data_dict[v][obj_want_to_check] > max_v:\n",
    "                max_v = data_dict[v][obj_want_to_check]\n",
    "                max_name = v\n",
    "    min_v = max_v\n",
    "    min_name = None\n",
    "    for v in data_dict.keys():\n",
    "        if data_dict[v][obj_want_to_check] != \"NaN\":\n",
    "            if data_dict[v][obj_want_to_check] < min_v:\n",
    "                min_v = data_dict[v][obj_want_to_check]\n",
    "                min_name = v\n",
    "    print (f\"The max value of {obj_want_to_check} is \", max_name, max_v)\n",
    "    print (f\"The min value of {obj_want_to_check} is \", min_name, min_v)\n",
    "    \n",
    "min_and_max(\"exercised_stock_options\")\n",
    "min_and_max(\"salary\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "### the input features we want to use \n",
    "### can be any key in the person-level dictionary (salary, director_fees, etc.) \n",
    "feature_1 = \"salary\"\n",
    "feature_2 = \"exercised_stock_options\"\n",
    "#fearure_3 = \"total_payments\"\n",
    "poi  = \"poi\"\n",
    "features_list = [poi, feature_1, feature_2]\n",
    "data = featureFormat(data_dict, features_list )\n",
    "poi, finance_features = targetFeatureSplit( data )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 13972 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "### in the \"clustering with 3 features\" part of the mini-project,\n",
    "### you'll want to change this line to \n",
    "### for f1, f2, _ in finance_features:\n",
    "### (as it's currently written, the line below assumes 2 features)\n",
    "for f1, f2 in finance_features:\n",
    "    plt.scatter( f1, f2 )\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 以下为使用 Sklearn 中的 KMeans 函数来生成、训练一个 K 均值分类器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 11752 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "### cluster here; create predictions of the cluster labels\n",
    "### for the data and store them to a list called pred\n",
    "from sklearn.cluster import KMeans\n",
    "\n",
    "clst = KMeans(n_clusters=2,n_init=100,max_iter=100)\n",
    "clst.fit(finance_features)\n",
    "pred = clst.predict(finance_features)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "### rename the \"name\" parameter when you change the number of features\n",
    "### so that the figure gets saved to a different file\n",
    "try:\n",
    "    Draw(pred, finance_features, poi, mark_poi=False, name=\"clusters_2.png\", f1_name=feature_1, f2_name=feature_2)\n",
    "except NameError:\n",
    "    print (\"no predictions object named pred found, no clusters to plot\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 此时对数据进行特征缩放\n",
    "这里是使用了两个特征缩放的缩放器，分别处理薪资和股票的数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 10576 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler\n",
    "f1_scaler = MinMaxScaler()\n",
    "f2_scaler = MinMaxScaler()\n",
    "feature1_list = []\n",
    "feature2_list = []\n",
    "for v in data_dict.keys():\n",
    "    if data_dict[v][feature_1] != \"NaN\" and data_dict[v][feature_2] != \"NaN\":\n",
    "        feature1_list.append([data_dict[v][feature_1]])\n",
    "        feature2_list.append([data_dict[v][feature_2]])\n",
    "\n",
    "\n",
    "feature1_list = f1_scaler.fit_transform(feature1_list)\n",
    "feature2_list = f2_scaler.fit_transform(feature2_list)\n",
    "new_finance_feature = []\n",
    "for feature in range(0,len(feature1_list)):\n",
    "    temp = [feature1_list[feature],feature2_list[feature]]\n",
    "    new_finance_feature.append(temp)\n",
    "#print(new_finance_feature)\n",
    "\n",
    "clst = KMeans(n_clusters=2,n_init=100,max_iter=100)\n",
    "clst.fit(finance_features)\n",
    "pred = clst.predict(finance_features)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "### rename the \"name\" parameter when you change the number of features\n",
    "### so that the figure gets saved to a different file\n",
    "try:\n",
    "    Draw(pred, finance_features, poi, mark_poi=False, name=\"clusters_scaled.png\", f1_name=feature_1, f2_name=feature_2)\n",
    "except NameError:\n",
    "    print (\"no predictions object named pred found, no clusters to plot\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.17962407]]\n",
      "[[0.00531945]]\n",
      "[[0.028622]]\n"
     ]
    }
   ],
   "source": [
    "# 测试两个值在缩放后的输出\n",
    "print(f1_scaler.transform([[200000.0]]))\n",
    "print(f2_scaler.transform([[200000]]))\n",
    "print(f2_scaler.transform([[1000000.0]]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "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.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
