{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Demo Notebook on Reading and Exploring the Studentlife Dataset\n",
    "\n",
    "In this example we download, preprocess and explore the [StudentLife Dataset](https://studentlife.cs.dartmouth.edu/dataset.html)<sup>[1]</sup>.\n",
    "\n",
    "\n",
    "1.: Wang, Rui, Fanglin Chen, Zhenyu Chen, Tianxing Li, Gabriella Harari, Stefanie Tignor, Xia Zhou, Dror Ben-Zeev, and Andrew T. Campbell. \"StudentLife: Assessing Mental Health, Academic Performance and Behavioral Trends of College Students using Smartphones.\" In Proceedings of the ACM Conference on Ubiquitous Computing. 2014."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import plotly.express as px\n",
    "import plotly.io as pio\n",
    "import warnings\n",
    "from math import nan, inf\n",
    "import pandas as pd\n",
    "import niimpy\n",
    "from niimpy.exploration.eda import countplot\n",
    "from niimpy.preprocessing import survey\n",
    "from niimpy.exploration.eda import categorical\n",
    "from kaggle.api.kaggle_api_extended import KaggleApi\n",
    "import zipfile\n",
    "\n",
    "# Plotly settings. Feel free to adjust to your needs.\n",
    "pio.renderers.default = \"png\"\n",
    "pio.templates.default = \"seaborn\"\n",
    "px.defaults.template = \"ggplot2\"\n",
    "px.defaults.color_continuous_scale = px.colors.sequential.RdBu\n",
    "px.defaults.width = 1200\n",
    "px.defaults.height = 482\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "# Login to Kaggle and download the dataset\n",
    "api = KaggleApi()\n",
    "api.authenticate()\n",
    "\n",
    "api.dataset_download_files('dartweichen/student-life', path=\".\")\n",
    "archive = zipfile.ZipFile('student-life.zip', 'r')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "survey_file = archive.open(f\"dataset/survey/PHQ-9.csv\")\n",
    "survey_data = pd.read_csv(survey_file)\n",
    "survey_data = survey_data.rename(columns={'uid': 'user'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "PHQ9_MAP = {\n",
    "    'Little interest or pleasure in doing things': \"PHQ9_1\",\n",
    "    'Feeling down, depressed, hopeless.': \"PHQ9_2\",\n",
    "    'Trouble falling or staying asleep, or sleeping too much.': \"PHQ9_3\",\n",
    "    'Feeling tired or having little energy': \"PHQ9_4\",\n",
    "    'Poor appetite or overeating': \"PHQ9_5\",\n",
    "    'Feeling bad about yourself or that you are a failure or have let yourself or your family down': \"PHQ9_6\",\n",
    "    'Trouble concentrating on things, such as reading the newspaper or watching television': \"PHQ9_7\",\n",
    "    'Moving or speaking so slowly that other people could have noticed. Or the opposite being so figety or restless that you have been moving around a lot more than usual': \"PHQ9_8\",\n",
    "    'Thoughts that you would be better off dead, or of hurting yourself': \"PHQ9_9\",\n",
    "}\n",
    "PHQ9_ANSWER_MAP = {\n",
    "    \"Not at all\": 0,\n",
    "    \"Several days\": 1,\n",
    "    \"More than half the days\": 2,\n",
    "    \"Nearly every day\": 3\n",
    "}\n",
    "survey_data = survey_data.rename(PHQ9_MAP, axis = 1)\n",
    "survey_data = survey.convert_survey_to_numerical_answer(\n",
    "    survey_data, id_map={\"PHQ9\": PHQ9_ANSWER_MAP}, use_prefix=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 34408 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = categorical.questionnaire_grouped_summary(\n",
    "    survey_data, \n",
    "    question='PHQ9_1',\n",
    "    group='type', \n",
    "    title='PHQ9 question: Little interest or pleasure in doing things',\n",
    "    xlabel='score', \n",
    "    ylabel='count',\n",
    "    width=800, \n",
    "    height=400\n",
    ")\n",
    "fig.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "pre_study_survey = survey_data[survey_data[\"type\"] == \"pre\"]\n",
    "scores = survey.sum_survey_scores(pre_study_survey, \"PHQ9\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "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>user</th>\n",
       "      <th>PHQ9</th>\n",
       "      <th>group</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>u00</td>\n",
       "      <td>2</td>\n",
       "      <td>minimal</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>u01</td>\n",
       "      <td>5</td>\n",
       "      <td>mild</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>u02</td>\n",
       "      <td>13</td>\n",
       "      <td>moderate</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>u03</td>\n",
       "      <td>2</td>\n",
       "      <td>minimal</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>u04</td>\n",
       "      <td>6</td>\n",
       "      <td>mild</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  user  PHQ9     group\n",
       "0  u00     2   minimal\n",
       "1  u01     5      mild\n",
       "2  u02    13  moderate\n",
       "3  u03     2   minimal\n",
       "4  u04     6      mild"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def PHQ9_sum_to_group(sum):\n",
    "    if sum < 5:\n",
    "        return \"minimal\"\n",
    "    elif sum < 10:\n",
    "        return \"mild\"\n",
    "    elif sum < 15:\n",
    "        return \"moderate\"\n",
    "    elif sum < 20:\n",
    "        return \"moderately severe\"\n",
    "    else:\n",
    "        return \"severe\"\n",
    "    \n",
    "scores[\"group\"] = scores[\"PHQ9\"].apply(PHQ9_sum_to_group)\n",
    "scores.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "activity_data = []\n",
    "for user_number in range(60):\n",
    "    user = f\"u{user_number:02}\"\n",
    "    try:\n",
    "        csvfile = archive.open(f\"dataset/sensing/activity/activity_{user}.csv\")\n",
    "        user_activity = pd.read_csv(csvfile)\n",
    "        user_activity[\"user\"] = user\n",
    "        activity_data.append(user_activity)\n",
    "    except:\n",
    "        pass\n",
    "activity_data = pd.concat(activity_data)\n",
    "\n",
    "# Reduce activity data to whether the user was active or not. Values 1 and 2 represent activity.\n",
    "activity_data = activity_data[activity_data[\" activity inference\"] != 3]\n",
    "activity_data[\"activity\"] = activity_data[\" activity inference\"].isin([1,2]).astype(int)\n",
    "\n",
    "# Set the timestamp as the index\n",
    "activity_data.set_index('timestamp',inplace=True)\n",
    "activity_data.index = pd.to_datetime(activity_data.index, unit='s')\n",
    "\n",
    "# Aggregate the data hourly\n",
    "activity_data = niimpy.util.aggregate(activity_data, \"1H\")\n",
    "activity_data = activity_data.reset_index(\"user\")\n",
    "activity_data = activity_data.replace([inf, -inf], nan).dropna(axis=0)\n",
    "activity_data[\"activity\"] = (activity_data[\"activity\"]*5+0.5).round(0).astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "activity_data = activity_data.reset_index().merge(\n",
    "    scores[[\"user\", \"group\"]],\n",
    "    how=\"inner\",\n",
    "    on=\"user\",\n",
    ").set_index(\"timestamp\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 98648 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = countplot.countplot(activity_data,\n",
    "                          fig_title='Activity data count for each user', \n",
    "                          plot_type='count', \n",
    "                          points='outliers',\n",
    "                          aggregation='user', \n",
    "                          user=None,\n",
    "                          column='activity',\n",
    "                          binning=False)\n",
    "\n",
    "fig.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 57404 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = countplot.countplot(activity_data, \n",
    "                          fig_title='Group level activity score distributions', \n",
    "                          plot_type='value', \n",
    "                          points='outliers',\n",
    "                          aggregation='group', \n",
    "                          user=None,\n",
    "                          column='activity',\n",
    "                          binning=False)\n",
    "\n",
    "fig.show()"
   ]
  }
 ],
 "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.11.3"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
