{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cf3750f4-b08d-4931-b2a0-81bc02a3356f",
   "metadata": {},
   "source": [
    "# Room-Occupancy Classification"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "humanitarian-burke",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "dedicated-employee",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('../datatest.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "quality-peoples",
   "metadata": {},
   "outputs": [],
   "source": [
    "signal = df['HumidityRatio'].values[:-2000]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "matched-current",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 2665 entries, 140 to 2804\n",
      "Data columns (total 7 columns):\n",
      " #   Column         Non-Null Count  Dtype  \n",
      "---  ------         --------------  -----  \n",
      " 0   date           2665 non-null   object \n",
      " 1   Temperature    2665 non-null   float64\n",
      " 2   Humidity       2665 non-null   float64\n",
      " 3   Light          2665 non-null   float64\n",
      " 4   CO2            2665 non-null   float64\n",
      " 5   HumidityRatio  2665 non-null   float64\n",
      " 6   Occupancy      2665 non-null   int64  \n",
      "dtypes: float64(5), int64(1), object(1)\n",
      "memory usage: 166.6+ KB\n"
     ]
    }
   ],
   "source": [
    "df.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "virgin-taylor",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 35608 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots()\n",
    "ax.plot(df['Humidity']/100)\n",
    "light = df['Light']/np.max(df['Light'])\n",
    "ax.plot(light)\n",
    "ax.plot(df['Temperature']/80)\n",
    "# ax.plot(df['HumidityRatio']*40)\n",
    "ax.plot(df['Occupancy'], ls='--')\n",
    "plt.show(fig)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "coordinated-celebrity",
   "metadata": {},
   "outputs": [],
   "source": [
    "occupancy = df.Occupancy.values\n",
    "humidity = df.Humidity.values\n",
    "light = df.Light.values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "chicken-teacher",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0.45353836, 0.07583515, 0.19437358, 0.28346148, 0.08540657,\n",
       "        0.04564834, 0.03092307, 0.03534065, 0.02282417, 0.01914285]),\n",
       " array([22.1    , 22.90225, 23.7045 , 24.50675, 25.309  , 26.11125,\n",
       "        26.9135 , 27.71575, 28.518  , 29.32025, 30.1225 ]),\n",
       " <BarContainer object of 10 artists>)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 4800 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(humidity[occupancy == 1], density=True)\n",
    "plt.hist(humidity[occupancy == 0], alpha=0.2, density=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "disturbed-bandwidth",
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.stats import gaussian_kde as kde"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "known-prairie",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 19832 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "n = len(df) // 2\n",
    "i = np.arange(len(df))\n",
    "np.random.shuffle(i)\n",
    "i = i[:n]\n",
    "h = humidity[i]\n",
    "o = occupancy[i]\n",
    "k1 = kde(h[o == 1])\n",
    "k0 = kde(h[o == 0])\n",
    "plt.scatter(humidity, k1.pdf(humidity))\n",
    "plt.scatter(humidity, k0.pdf(humidity))\n",
    "plt.scatter(humidity, k1.pdf(humidity), label=\"occupied\")\n",
    "plt.scatter(humidity, k0.pdf(humidity), label=\"unoccupied\")\n",
    "plt.title(\"Distribution of Light by Class\")\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "annual-physics",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 14824 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "n = len(df) // 2\n",
    "i = np.arange(len(df))\n",
    "np.random.shuffle(i)\n",
    "i = i[:n]\n",
    "l = light[i]\n",
    "o = occupancy[i]\n",
    "k1 = kde(l[o == 1])\n",
    "k0 = kde(l[o == 0])\n",
    "plt.scatter(light, k1.pdf(light), label=\"occupied\")\n",
    "plt.scatter(light, k0.pdf(light), label=\"unoccupied\")\n",
    "plt.title(\"Distribution of Light by Class\")\n",
    "plt.legend()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "tough-austria",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "31.4725"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "humidity[np.argmin(np.abs(k0.pdf(humidity) - k1.pdf(humidity)))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "ruled-musical",
   "metadata": {},
   "outputs": [],
   "source": [
    "# test a threshold-based classifier based on light\n",
    "light_feature = (light > 0.25)*1\n",
    "occupancy = df.Occupancy.values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "medium-speed",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import confusion_matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "frank-bennett",
   "metadata": {},
   "outputs": [],
   "source": [
    "confuse = confusion_matrix(light_feature, occupancy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "controlling-johns",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f76fa83ed00>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 5144 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(confuse)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "referenced-fashion",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.60600375, 0.        ],\n",
       "       [0.02926829, 0.36472795]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "confuse/len(occupancy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "specialized-anchor",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "133"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(df)//20"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "light-helen",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = len(df)*6//10\n",
    "occupancy = df.Occupancy.values[0:n]\n",
    "errors = []\n",
    "thresholds = np.linspace(0, 1, 100)\n",
    "for thresh in thresholds:\n",
    "    light_feature = (light[0:n] > thresh)*1\n",
    "    humidity_feature = (humidity[0:n] > 25.37)*1\n",
    "#     feature = ((light_feature + humidity_feature) == 2)*1\n",
    "    light_feature = (light[0:n] > 0.2)*1\n",
    "    feature = (light_feature + 0.7*humidity_feature > 2*thresh)*1\n",
    "    confuse = confusion_matrix(feature, occupancy)/n\n",
    "#     det = np.linalg.det(confuse/np.linalg.norm(confuse))\n",
    "    errors.append(confuse[0,0] + confuse[1,1] - confuse[0,1] - confuse[1,1])\n",
    "#     errors = confuse[0,0]\n",
    "del confuse, thresh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "danish-paint",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f76fa7c5220>]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 6304 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(thresholds, errors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "lasting-still",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 6392 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.50093809 0.        ]\n",
      " [0.13433396 0.36472795]]\n"
     ]
    }
   ],
   "source": [
    "occupancy = df.Occupancy.values\n",
    "thresh = thresholds[np.argmax(errors)]\n",
    "# light_feature = (light.values > thresh)*1\n",
    "# feature = light_feature\n",
    "light_feature = (light > 0.1182)*1\n",
    "humidity_feature = (humidity > 25.37)*1\n",
    "feature = (light_feature + 0.5*humidity_feature > 2*thresh)*1\n",
    "confuse = confusion_matrix(feature, occupancy)/len(occupancy)\n",
    "plt.imshow(confuse)\n",
    "plt.title(f\"thresh={thresh:.4f}\")\n",
    "plt.show()\n",
    "print(confuse)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "binding-incident",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 6484 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.60600375 0.        ]\n",
      " [0.02926829 0.36472795]]\n"
     ]
    }
   ],
   "source": [
    "occupancy = df.Occupancy.values\n",
    "thresh = 0.1182\n",
    "light_feature = (light > thresh)*1\n",
    "feature = light_feature\n",
    "confuse = confusion_matrix(feature, occupancy)/len(occupancy)\n",
    "plt.imshow(confuse)\n",
    "plt.title(f\"thresh={thresh:.4f}\")\n",
    "plt.show()\n",
    "print(confuse)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "standing-footage",
   "metadata": {},
   "outputs": [],
   "source": [
    "humidity_feature = (humidity > 25.37)*1\n",
    "occupancy = df.Occupancy.values\n",
    "confuse = confusion_matrix(humidity_feature, occupancy)/len(occupancy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "direct-nirvana",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.51594747, 0.07879925],\n",
       "       [0.11932458, 0.28592871]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "confuse"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "passive-index",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 2, 2, ..., 2, 2, 2])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "light_feature + humidity_feature"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a0cdc07a-9600-4bc3-8f31-627ac3329da7",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
