{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "<p align=\"center\">\n",
    "    <img src=\"https://github.com/GeostatsGuy/GeostatsPy/blob/master/TCG_color_logo.png?raw=true\" width=\"220\" height=\"240\" />\n",
    "\n",
    "</p>\n",
    "\n",
    "### Interactive Workflow of Principal Component Analysis\n",
    "    \n",
    "#### The University of Texas at Austin, PGE 2020 SURI, Undergraduation Research Internship,\n",
    "    \n",
    " #### Arham Junaid, Undergraduate Student, The University of Texas at Austin,\n",
    " \n",
    " #### [LinkedIn](https://www.linkedin.com/in/arhamjunaid)\n",
    "\n",
    " #### Michael Pyrcz, Associate Professor, University of Texas at Austin,\n",
    "    \n",
    " ##### [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig)  | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1) | [GeostatsPy](https://github.com/GeostatsGuy/GeostatsPy),\n",
    "\n",
    "#### Introduction\n",
    "\n",
    "Hello and welcome to my workflow relating to Principal Component Analysis. I built out this well-documented workflow with Prof. Pyrcz as part of a SURI undergraduate research project at The University of Texas at Austin.\n",
    "\n",
    "I am Arham Junaid, currently a student doing his undergraduate studies relating to the Energy industry while exploring various Machine Learning methodologies. Principal Component Analysis is an example of inferential machine learning, essentially a method in which your data can be analyzed for dimensional reduction, relationships between variables and making predictions based on the relationships determined. \n",
    "\n",
    "For more check out Prof. Pyrcz's YouTube channel [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig). For the walkthrough video of this workflow go here [walkthrough](TBD). Here's some basic concepts on Principal Component Analysis.\n",
    "\n",
    "#### Principal Component Analysis\n",
    "\n",
    "Principal Component Analysis one of a variety of methods for dimensional reduction:\n",
    "\n",
    "Dimensional reduction transforms the data to a lower dimension\n",
    "\n",
    "* Given features, $𝑋_1,\\dots,𝑋_𝑚$  we would require ${m \\choose 2}=\\frac{𝑚 \\cdot (𝑚−1)}{2}$ scatter plots to visualize just the two-dimensional scatter plots.\n",
    "\n",
    "* Once we have 4 or more variables understanding our data gets very hard.\n",
    "\n",
    "* Recall the curse of dimensionality, impact inference, modeling and visualization. \n",
    "\n",
    "One solution, is to find a good lower dimensional, $𝑝$,  representation of the original dimensions $𝑚$\n",
    "\n",
    "Benefits of Working in a Reduced Dimensional Representation:\n",
    "\n",
    "1. Data storage / Computational Time\n",
    "\n",
    "2. Easier visualization\n",
    "\n",
    "3. Also takes care of multicollinearity \n",
    "\n",
    "#### Orthogonal Transformation \n",
    "\n",
    "Convert a set of observations into a set of linearly uncorrelated variables known as principal components\n",
    "\n",
    "* The number of principal components ($k$) available are min⁡($𝑛−1,𝑚$) \n",
    "\n",
    "* Limited by the variables/features, $𝑚$, and the number of data\n",
    "\n",
    "Components are ordered\n",
    "\n",
    "* First component describes the larges possible variance / accounts for as much variability as possible\n",
    "* Next component describes the largest possible remaining variance \n",
    "* Up to the maximum number of principal components\n",
    "\n",
    "Eigen Values / Eigen Vectors\n",
    "\n",
    "* The Eigen values are the variance explained for each component. \n",
    "* The Eigen vectors of the data covariance matrix are the principal components and the Eigen  \n",
    "* Out of scope – just making the linkage\n",
    "\n",
    "#### Objective\n",
    "In this workflow, we will explore 4 basic aspects of PCA. These include:\n",
    "\n",
    "  - Orthogonal rotation and the incorporation of eigen math\n",
    "\n",
    "  - Forward and backward transformations\n",
    "\n",
    "  - Variance Explained\n",
    "\n",
    "  - Dimensionality Reduction\n",
    "\n",
    "PCA allows is to find good relationships within lower dimensions to allow for greater representation of a multivariate data set and has benefits including ease of visualization, multicollinearity and a reduction in data storage and computational analysis.\n",
    "\n",
    "It is hoped that this interactive version of PCA will provide greater understanding with regards to the benefit of the method in general application.\n",
    "\n",
    "#### Getting Started\n",
    "Here are the steps to get setup in Python with the GeostatsPy package:\n",
    "1.\tInstall Anaconda 3 on your machine (https://www.anaconda.com/download/).\n",
    "2.\tFrom Anaconda Navigator (within Anaconda3 group), go to the environment tab, click on base (root) green arrow and open a terminal.\n",
    "3.\tIn the terminal type: pip install geostatspy.\n",
    "4.\tOpen Jupyter and in the top block get started by copy and pasting the code block below from this Jupyter Notebook to start using the geostatspy functionality.\n",
    "\n",
    "You will need to copy the data file to your working directory. They are available here:\n",
    "   - Tabular data - unconv_MV_v2.csv at https://git.io/fjmBH.\n",
    "\n",
    "#### Install Packages\n",
    "\n",
    "For this interactive workflow to work, we need to install several packages relating to display features, widgets and data analysis interpretation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os                                                 # to set current working directory \n",
    "from sklearn.decomposition import PCA                     # PCA program from scikit learn (package for machine learning)\n",
    "from sklearn.preprocessing import StandardScaler          # standardize variables to mean of 0.0 and variance of 1.0\n",
    "import pandas as pd                                       # DataFrames and plotting\n",
    "import pandas.plotting as pd_plot                         # matrix scatter plots\n",
    "import numpy as np                                        # arrays and matrix math\n",
    "import matplotlib.pyplot as plt                           # plotting\n",
    "import seaborn as sns\n",
    "import ipywidgets as widgets\n",
    "from ipywidgets import interactive, interact              # widgets and interactivity\n",
    "from ipywidgets import widgets                            \n",
    "from ipywidgets import Layout\n",
    "from ipywidgets import Label\n",
    "import matplotlib.transforms as transforms\n",
    "import math\n",
    "from ipywidgets import VBox, HBox\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "cmap = plt.cm.inferno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### The Data Set\n",
    "Next, let’s go ahead and load the data set we are going to be working with. We’re able to view the variables relating to production.\n",
    "This dataset has variables from 1,000 unconventional wells including:\n",
    " -\twell average porosity\n",
    " - \tlog transform of permeability (to linearize the relationships with other variables)\n",
    " -\taccoustic impedance (kg/m^3 x m/s x 10^6)\n",
    " -\tbrittness ratio (%)\n",
    " -\ttotal organic carbon (%)\n",
    " -\tvitrinite reflectance (%)\n",
    " -\tinitial production 90 day average (MCFPD).\n",
    " -\tscaled production\n",
    " \n",
    "First copy the \"unconv_MV_v2.csv\" comma delimited file from https://github.com/GeostatsGuy/GeoDataSets to your working directory, then run this command to read the file into a DataFrame object (part of Pandas package)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "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>Sample</th>\n",
       "      <th>Por</th>\n",
       "      <th>LogPerm</th>\n",
       "      <th>AI</th>\n",
       "      <th>Brittle</th>\n",
       "      <th>TOC</th>\n",
       "      <th>VR</th>\n",
       "      <th>Production</th>\n",
       "      <th>Prod2Scaled</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>15.91</td>\n",
       "      <td>1.67</td>\n",
       "      <td>3.06</td>\n",
       "      <td>14.05</td>\n",
       "      <td>1.36</td>\n",
       "      <td>1.85</td>\n",
       "      <td>177.381958</td>\n",
       "      <td>1897.657798</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>15.34</td>\n",
       "      <td>1.65</td>\n",
       "      <td>2.60</td>\n",
       "      <td>31.88</td>\n",
       "      <td>1.37</td>\n",
       "      <td>1.79</td>\n",
       "      <td>1479.767778</td>\n",
       "      <td>2745.732996</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>20.45</td>\n",
       "      <td>2.02</td>\n",
       "      <td>3.13</td>\n",
       "      <td>63.67</td>\n",
       "      <td>1.79</td>\n",
       "      <td>2.53</td>\n",
       "      <td>4421.221583</td>\n",
       "      <td>5835.130524</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>11.95</td>\n",
       "      <td>1.14</td>\n",
       "      <td>3.90</td>\n",
       "      <td>58.81</td>\n",
       "      <td>0.40</td>\n",
       "      <td>2.03</td>\n",
       "      <td>1488.317629</td>\n",
       "      <td>2132.237219</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>19.53</td>\n",
       "      <td>1.83</td>\n",
       "      <td>2.57</td>\n",
       "      <td>43.75</td>\n",
       "      <td>1.40</td>\n",
       "      <td>2.11</td>\n",
       "      <td>5261.094919</td>\n",
       "      <td>6282.254735</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Sample    Por  LogPerm    AI  Brittle   TOC    VR   Production  Prod2Scaled\n",
       "0       1  15.91     1.67  3.06    14.05  1.36  1.85   177.381958  1897.657798\n",
       "1       2  15.34     1.65  2.60    31.88  1.37  1.79  1479.767778  2745.732996\n",
       "2       3  20.45     2.02  3.13    63.67  1.79  2.53  4421.221583  5835.130524\n",
       "3       4  11.95     1.14  3.90    58.81  0.40  2.03  1488.317629  2132.237219\n",
       "4       5  19.53     1.83  2.57    43.75  1.40  2.11  5261.094919  6282.254735"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "#os.chdir(r'C:\\PGE383')\n",
    "#df=pd.read_csv(\"unconv_MV_v2.csv\")\n",
    "df=pd.read_csv(r\"https://raw.githubusercontent.com/GeostatsGuy/GeoDataSets/master/unconv_MV_v2.csv\")\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We are also able to view some basic summary statistics relating to our variables and transpose the data set to make it easier for us to work with."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "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>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Por</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>14.950460</td>\n",
       "      <td>3.029634</td>\n",
       "      <td>5.400000</td>\n",
       "      <td>12.857500</td>\n",
       "      <td>14.985000</td>\n",
       "      <td>17.080000</td>\n",
       "      <td>24.65000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LogPerm</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>1.398880</td>\n",
       "      <td>0.405966</td>\n",
       "      <td>0.120000</td>\n",
       "      <td>1.130000</td>\n",
       "      <td>1.390000</td>\n",
       "      <td>1.680000</td>\n",
       "      <td>2.58000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AI</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>2.982610</td>\n",
       "      <td>0.577629</td>\n",
       "      <td>0.960000</td>\n",
       "      <td>2.577500</td>\n",
       "      <td>3.010000</td>\n",
       "      <td>3.360000</td>\n",
       "      <td>4.70000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Brittle</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>49.769980</td>\n",
       "      <td>14.944955</td>\n",
       "      <td>3.030000</td>\n",
       "      <td>39.722500</td>\n",
       "      <td>49.680000</td>\n",
       "      <td>59.170000</td>\n",
       "      <td>93.47000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TOC</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>1.003810</td>\n",
       "      <td>0.504978</td>\n",
       "      <td>-0.260000</td>\n",
       "      <td>0.640000</td>\n",
       "      <td>0.995000</td>\n",
       "      <td>1.360000</td>\n",
       "      <td>2.71000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>VR</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>1.991170</td>\n",
       "      <td>0.308194</td>\n",
       "      <td>0.900000</td>\n",
       "      <td>1.810000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.172500</td>\n",
       "      <td>2.90000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Production</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>2247.295809</td>\n",
       "      <td>1464.256312</td>\n",
       "      <td>2.713535</td>\n",
       "      <td>1191.369560</td>\n",
       "      <td>1976.487820</td>\n",
       "      <td>3023.594214</td>\n",
       "      <td>12568.64413</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Prod2Scaled</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>3237.154325</td>\n",
       "      <td>1507.552730</td>\n",
       "      <td>2.713535</td>\n",
       "      <td>2120.961071</td>\n",
       "      <td>2991.762748</td>\n",
       "      <td>4105.623405</td>\n",
       "      <td>12568.64413</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              count         mean          std       min          25%  \\\n",
       "Por          1000.0    14.950460     3.029634  5.400000    12.857500   \n",
       "LogPerm      1000.0     1.398880     0.405966  0.120000     1.130000   \n",
       "AI           1000.0     2.982610     0.577629  0.960000     2.577500   \n",
       "Brittle      1000.0    49.769980    14.944955  3.030000    39.722500   \n",
       "TOC          1000.0     1.003810     0.504978 -0.260000     0.640000   \n",
       "VR           1000.0     1.991170     0.308194  0.900000     1.810000   \n",
       "Production   1000.0  2247.295809  1464.256312  2.713535  1191.369560   \n",
       "Prod2Scaled  1000.0  3237.154325  1507.552730  2.713535  2120.961071   \n",
       "\n",
       "                     50%          75%          max  \n",
       "Por            14.985000    17.080000     24.65000  \n",
       "LogPerm         1.390000     1.680000      2.58000  \n",
       "AI              3.010000     3.360000      4.70000  \n",
       "Brittle        49.680000    59.170000     93.47000  \n",
       "TOC             0.995000     1.360000      2.71000  \n",
       "VR              2.000000     2.172500      2.90000  \n",
       "Production   1976.487820  3023.594214  12568.64413  \n",
       "Prod2Scaled  2991.762748  4105.623405  12568.64413  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = df.iloc[:,1:9]                                  # copy all rows and columns 1 through 9, note 0 column is removed\n",
    "df.describe().transpose()                            # calculate summary statistics for the data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can go about ensuring the negative values are removed, namely for TOC and Brittleness, since those are not possible and we can set our data values into a single Data Frame."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "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>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Por</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>14.950460</td>\n",
       "      <td>3.029634</td>\n",
       "      <td>5.400000</td>\n",
       "      <td>12.857500</td>\n",
       "      <td>14.985000</td>\n",
       "      <td>17.080000</td>\n",
       "      <td>24.65000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LogPerm</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>1.398880</td>\n",
       "      <td>0.405966</td>\n",
       "      <td>0.120000</td>\n",
       "      <td>1.130000</td>\n",
       "      <td>1.390000</td>\n",
       "      <td>1.680000</td>\n",
       "      <td>2.58000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AI</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>2.982610</td>\n",
       "      <td>0.577629</td>\n",
       "      <td>0.960000</td>\n",
       "      <td>2.577500</td>\n",
       "      <td>3.010000</td>\n",
       "      <td>3.360000</td>\n",
       "      <td>4.70000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Brittle</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>49.769980</td>\n",
       "      <td>14.944955</td>\n",
       "      <td>3.030000</td>\n",
       "      <td>39.722500</td>\n",
       "      <td>49.680000</td>\n",
       "      <td>59.170000</td>\n",
       "      <td>93.47000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TOC</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>1.006170</td>\n",
       "      <td>0.499838</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.640000</td>\n",
       "      <td>0.995000</td>\n",
       "      <td>1.360000</td>\n",
       "      <td>2.71000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>VR</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>1.991170</td>\n",
       "      <td>0.308194</td>\n",
       "      <td>0.900000</td>\n",
       "      <td>1.810000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.172500</td>\n",
       "      <td>2.90000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Production</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>2247.295809</td>\n",
       "      <td>1464.256312</td>\n",
       "      <td>2.713535</td>\n",
       "      <td>1191.369560</td>\n",
       "      <td>1976.487820</td>\n",
       "      <td>3023.594214</td>\n",
       "      <td>12568.64413</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Prod2Scaled</th>\n",
       "      <td>1000.0</td>\n",
       "      <td>3237.154325</td>\n",
       "      <td>1507.552730</td>\n",
       "      <td>2.713535</td>\n",
       "      <td>2120.961071</td>\n",
       "      <td>2991.762748</td>\n",
       "      <td>4105.623405</td>\n",
       "      <td>12568.64413</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              count         mean          std       min          25%  \\\n",
       "Por          1000.0    14.950460     3.029634  5.400000    12.857500   \n",
       "LogPerm      1000.0     1.398880     0.405966  0.120000     1.130000   \n",
       "AI           1000.0     2.982610     0.577629  0.960000     2.577500   \n",
       "Brittle      1000.0    49.769980    14.944955  3.030000    39.722500   \n",
       "TOC          1000.0     1.006170     0.499838  0.000000     0.640000   \n",
       "VR           1000.0     1.991170     0.308194  0.900000     1.810000   \n",
       "Production   1000.0  2247.295809  1464.256312  2.713535  1191.369560   \n",
       "Prod2Scaled  1000.0  3237.154325  1507.552730  2.713535  2120.961071   \n",
       "\n",
       "                     50%          75%          max  \n",
       "Por            14.985000    17.080000     24.65000  \n",
       "LogPerm         1.390000     1.680000      2.58000  \n",
       "AI              3.010000     3.360000      4.70000  \n",
       "Brittle        49.680000    59.170000     93.47000  \n",
       "TOC             0.995000     1.360000      2.71000  \n",
       "VR              2.000000     2.172500      2.90000  \n",
       "Production   1976.487820  3023.594214  12568.64413  \n",
       "Prod2Scaled  2991.762748  4105.623405  12568.64413  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "num = df._get_numeric_data()                         # get the numerical values\n",
    "num[num < 0] = 0                                     # truncate negative values to 0.0\n",
    "df.describe().transpose()                            # calculate summary statistics for the data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In order to go about dimensionality reduction, a useful first step is to develop a correlation matrix. The higher the magnitude of correlation between your 2 variables, the more likely it is that your principal component scores will be able to account for a greater variance of your data.\n",
    "\n",
    "* PCA assumes that there is linear correlation between features, this does exist in our dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 79100 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "_=sns.heatmap(df.corr(),annot=True,cmap=cmap)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the correlation matrix above, can observe a mix of bivariate data, and linear correlation magnitudes and for additional visualization, we can take a look at the matrix scatter plot as we look to narrow down to 2 variables to allow for analysis of our data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 317912 characters]",
      "text/plain": [
       "<Figure size 700x700 with 64 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "pd_plot.scatter_matrix(df, alpha = 0.1,              # pandas matrix scatter plot\n",
    "    figsize=(7, 7),color = 'black', hist_kwds={'color':['grey']})\n",
    "plt.suptitle(\"Matrix Scatter Plot\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Interactive Exercise #1: Orthogonal Rotation\n",
    "\n",
    "\n",
    "For our first example, let’s explore the power of orthogonal rotation. \n",
    "* Eigen values and eigen vectors are based on the idea of the rotation of your axis. For our example, 2 variables, Por and TOC, with a relatively high correlation coefficient, were chosen to explore this idea further. \n",
    "* For reduced computational load, only 100 values have been selected but you’re welcome to incorporate more of the data by copying and changing the code. \n",
    "* For principle component scores to be calculated, the data first needs to be standardized. \n",
    "\n",
    "We can have a go at visualizing how the data points alter as the angle of rotation varies and how much of the variance is influenced by rotation coordinate 1 and rotational coordinate 2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_data_por_perm = df[[\"Por\",\"TOC\"]]                # extract just por and TOC, 100 samples\n",
    "my_data_por_perm =my_data_por_perm.iloc[0:100]\n",
    "features = ['Por','TOC']\n",
    "x = my_data_por_perm.loc[:,features].values\n",
    "s = StandardScaler()\n",
    "s.fit(x)\n",
    "x = s.transform(x)                                  # standardize the data features to mean = 0, var = 1.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we have our data standardized, we can take a look at a scatter plot of the 2 variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Standardized TOC')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 39784 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "figure, a = plt.subplots()\n",
    "a.scatter(my_data_por_perm[\"Por\"],my_data_por_perm[\"TOC\"],s=None, c=\"darkorange\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.8, linewidths=1.0, edgecolors=\"black\")    \n",
    "a.set_title('Standardized Porosity vs Standardized TOC'); \n",
    "a.set_xlabel(\"Standardized Porosity\")\n",
    "a.set_ylabel(\"Standardized TOC\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the plot, there seems to be a seemingly linear trend.\n",
    "\n",
    "We can now visualize how the data is rotated in order to understand the proportion of the variance for each rotated coordinate. The rotational coordinates are determined by simple trigonometric functions, sine and cosine to determine their new location."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "global xdata                                        #create global values to allow for orthoganal rotation and visualization\n",
    "global ydata\n",
    "def pc_slider(Angle):\n",
    "    global xdata\n",
    "    global ydata\n",
    "    fig15, ((ax15,ax16)) = plt.subplots(1, 2,figsize=(15,6), constrained_layout=True)\n",
    "    fig15.subplots_adjust(wspace=.5,hspace = .5)\n",
    "    \n",
    "    \n",
    "    base = plt.gca().transData\n",
    "    #print(base)\n",
    "    rot = transforms.Affine2D().rotate_deg(int(Angle))\n",
    "    line=ax16.plot(x[:,0],x[:,1], 'o', transform= rot + base, c = 'black', alpha = 0.3)\n",
    "    \n",
    "    xdata=x[:,0]*math.cos(math.radians(int(Angle)))-x[:,1]*math.sin(math.radians(int(Angle)))\n",
    "    ydata=x[:,1]*math.cos(math.radians(int(Angle)))+x[:,0]*math.sin(math.radians(int(Angle)))\n",
    "    \n",
    "    eigen = np.zeros([2,2])\n",
    "    eigen[0,0] = math.cos(Angle*math.pi/180.0)\n",
    "    eigen[1,0] = math.sin(Angle*math.pi/180.0)\n",
    "    eigen[0,1] = -1*math.sin(Angle*math.pi/180.0)\n",
    "    eigen[1,1] = math.cos(Angle*math.pi/180.0)\n",
    "    \n",
    "    df2 = pd.DataFrame({'x':xdata, 'y':ydata})\n",
    "    data = df2.values\n",
    "    lists=[]\n",
    "    \n",
    "    ydataZeroed = np.zeros(len(ydata))\n",
    "\n",
    "    ax16.plot(xdata, ydataZeroed,\"or\", c = 'red', alpha = 0.3)\n",
    "    ax16.plot(ydataZeroed, ydata,\"or\", c= 'blue', alpha = 0.3)\n",
    "    ax16.set_xlim(left=-3.5, right=3.5)\n",
    "    ax16.set_ylim(bottom=-3.5, top=3.5)\n",
    "    \n",
    "    ax16.set_title(\"Arbitrary Data Projection\");ax16.set_xlabel('Projected Feature 1'); ax16.set_ylabel('Projected Feature 2')\n",
    "    labels = 'Feature 2 Variance', 'Feature 1 Variance'\n",
    "    sizes = []\n",
    "    \n",
    "    print('Your Estimated Principal Component/Eigen Vector #1 = ' + str(eigen[:,0]))\n",
    "    print('Your Estimated Principal Component/Eigen Vector #2 = ' + str(eigen[:,1]))\n",
    "    \n",
    "    sumOfVariance=df2.var()['x']+df2.var()['y']\n",
    "    sizes.append(df2.var()['x']/sumOfVariance)\n",
    "    sizes.append(df2.var()['y']/sumOfVariance)\n",
    "    n = ax15.pie(sizes, autopct='%1.2f%%',colors = ['red','blue'],shadow=True,startangle=90)\n",
    "    n[0][0].set_alpha(0.5); n[0][1].set_alpha(0.5)\n",
    "    ax15.axis('equal')\n",
    "    ax15.legend(sizes, labels=labels,loc='upper left')\n",
    "#    plt.tight_layout()\n",
    "    plt.subplots_adjust(left=0.0, bottom=0.0, right=1.0, top=1.0, wspace=0.1, hspace=0.1)\n",
    "    plt.show()\n",
    "    \n",
    "x0 = widgets.Text(value='                                   Interactive Feature Projection - Orthogonal Rotation, Arham Junaid and Dr. Michael Pyrcz, The University of Texas at Austin',layout=Layout(width='950px', height='30px'))\n",
    "x1 = widgets.IntSlider(min=0, max = 180, value = 0, description = 'Angle',orientation='horizontal')\n",
    "uik2 = widgets.VBox([x0,x1],)\n",
    "interactive_plot = widgets.interactive_output(pc_slider, {'Angle': x1})\n",
    "interactive_plot.clear_output(wait = True)               # reduce flickering by delaying plot updating"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Interactive Feature Projection with Arbitrary Rotation\n",
    "\n",
    "#### Arham Junaid, SURI Student, Michael Pyrcz, Associate Professor, University of Texas at Austin \n",
    "\n",
    "Observed the partitioning of variance over 2 new features through orthogonal projection / rotation.\n",
    "\n",
    "### The Inputs\n",
    "\n",
    "* **Angle**: data rotation angle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e6ac47b17de14f2b9881ba53a0024e5d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(Text(value='                                   Interactive Feature Projection - Orthogonal Rota…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e9b4859ac63f47e8868985ff78e3403e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display(uik2,interactive_plot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now convert our rotated coordinates back in the data frame to do some analysis.\n",
    "\n",
    "Now let's visualize the principal components in a more intuitive manner."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "global xdata                                        #create global values to allow for orthoganal rotation and visualization\n",
    "global ydata\n",
    "def pc_slider(Angle):\n",
    "    global xdata\n",
    "    global ydata\n",
    "    fig15, ((ax15,ax16)) = plt.subplots(1, 2,figsize=(15,6), constrained_layout=True)\n",
    "    fig15.subplots_adjust(wspace=.5,hspace = .5)\n",
    "    \n",
    "    base = plt.gca().transData\n",
    "    #print(base)\n",
    "    rot = transforms.Affine2D().rotate_deg(int(Angle))\n",
    "    #line=ax16.plot(x[:,0],x[:,1], 'o', transform= rot + base, c = 'black', alpha = 0.3)\n",
    "    line=ax16.plot(x[:,0],x[:,1], 'o', c = 'black', alpha = 0.3)\n",
    "    \n",
    "    xdata=x[:,0]*math.cos(math.radians(int(Angle)))-x[:,1]*math.sin(math.radians(int(Angle)))\n",
    "    ydata=x[:,1]*math.cos(math.radians(int(Angle)))+x[:,0]*math.sin(math.radians(int(Angle)))\n",
    "    \n",
    "    eigen = np.zeros([2,2])\n",
    "    eigen[0,0] = math.cos(Angle*math.pi/180.0)\n",
    "    eigen[1,0] = math.sin(Angle*math.pi/180.0)\n",
    "    eigen[0,1] = -1*math.sin(Angle*math.pi/180.0)\n",
    "    eigen[1,1] = math.cos(Angle*math.pi/180.0)\n",
    "    \n",
    "    df2 = pd.DataFrame({'x':xdata, 'y':ydata})\n",
    "    data = df2.values\n",
    "    lists=[]\n",
    "    \n",
    "    ydataZeroed = np.zeros(len(ydata))\n",
    "\n",
    "    rotinv = transforms.Affine2D().rotate_deg(int(-Angle)) \n",
    "    ax16.plot(xdata, ydataZeroed,\"or\", c = 'red', alpha = 0.3,transform= rotinv + base)\n",
    "    ax16.plot(ydataZeroed, ydata,\"or\", c= 'blue', alpha = 0.3,transform= rotinv + base)\n",
    "    ax16.set_xlim(left=-3.5, right=3.5)\n",
    "    ax16.set_ylim(bottom=-3.5, top=3.5)\n",
    "    \n",
    "    ax16.set_title(\"Data and Arbitrary Feature Projection Components\");ax16.set_xlabel('Standardized Porosity'); ax16.set_ylabel('Standardized TOC')\n",
    "    labels = 'Feature 2 Variance', 'Feature 1 Variance'\n",
    "    sizes = []\n",
    "    \n",
    "#     print('Your Estimated Principal Component/Eigen Vector #1 = ' + str(eigen[:,0]))\n",
    "#     print('Your Estimated Principal Component/Eigen Vector #2 = ' + str(eigen[:,1]))\n",
    "    \n",
    "    sumOfVariance=df2.var()['x']+df2.var()['y']\n",
    "    sizes.append(df2.var()['x']/sumOfVariance)\n",
    "    sizes.append(df2.var()['y']/sumOfVariance)\n",
    "    n = ax15.pie(sizes, autopct='%1.2f%%',colors = ['red','blue'],shadow=True,startangle=90)\n",
    "    n[0][0].set_alpha(0.5); n[0][1].set_alpha(0.5)\n",
    "    ax15.axis('equal')\n",
    "    ax15.legend(sizes, labels=labels,loc='upper left')\n",
    "    ax15.set_title('Variance for Arbitrary Feature Projection Components')\n",
    "#    plt.tight_layout()\n",
    "    plt.subplots_adjust(left=0.0, bottom=0.0, right=1.0, top=1.0, wspace=0.1, hspace=0.1)\n",
    "    plt.show()\n",
    "    \n",
    "x0 = widgets.Text(value='                                            Interactive Feature Projection - Orthogonal Rotation, Dr. Michael Pyrcz, The University of Texas at Austin',layout=Layout(width='950px', height='30px'))\n",
    "x1 = widgets.IntSlider(min=0, max = 180, value = 0, description = 'Angle',orientation='horizontal',continuous_update=False)\n",
    "uik2 = widgets.VBox([x0,x1],)\n",
    "interactive_plot = widgets.interactive_output(pc_slider, {'Angle': x1})\n",
    "interactive_plot.clear_output(wait = True)               # reduce flickering by delaying plot updating"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Interactive Feature Projection with Arbitrary Rotation\n",
    "\n",
    "#### Michael Pyrcz, Associate Professor, University of Texas at Austin \n",
    "\n",
    "Observed the partitioning of variance over 2 new features through orthogonal projection / rotation.\n",
    "\n",
    "### The Inputs\n",
    "\n",
    "* **Angle**: data rotation angle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4ca3f5ac03b843dea9b3fd4f38e0f40d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(Text(value='                                            Interactive Feature Projection - Orthog…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4949b7d69a3d48b497c3ea4e5550a103",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display(uik2,interactive_plot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Below, we can see the calculation of the covariance matrix and the proportion of variance explained by each Principal Component Score as determined by PCA. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0.707  0.707]\n",
      " [-0.707  0.707]]\n",
      "Variance explained by PC1 and PC2 = [0.8596 0.1404]\n"
     ]
    }
   ],
   "source": [
    "n_components = 2\n",
    "pca = PCA(n_components=n_components)\n",
    "pca.fit(x)\n",
    "print(np.round(pca.components_,3))\n",
    "print('Variance explained by PC1 and PC2 =', np.round(pca.explained_variance_ratio_,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "At angle 0, the covariance tells us that both variables have the same amount of influence on the variance. This changes with the angle of rotation. \n",
    "\n",
    "The proportion of variance explained by the first principal component score is 85.96%. \n",
    "\n",
    "**Exercise:** Play around with the rotation above and see what angle provides the variance determined by PCA"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Interative Workflow #2: Forward and Backward Transformations\n",
    "\n",
    "Below you can choose an arbitrary value for a new data point, in blue. As you play around with where the new data point is placed, you notice that the data point can only go along the de-standardized line in graph 6. This is a key aspect of PCA relating to how the data is transformed based on the Principal Component scores calculated.\n",
    "\n",
    "Here is a flowchart of the transformations which take place:\n",
    "\n",
    "   ![alt text](flowChartFinal.png \"Title\")\n",
    "   \n",
    "   \n",
    "\n",
    "\n",
    "First, the PCA code is written to calculate the location of data points in each of these state spaces."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "mu = np.mean(x, axis=0)\n",
    "sd = np.std(x, axis=0)\n",
    "x_stand = StandardScaler().fit_transform(x)                     # standardize the data features to mean = 0, var = 1.0\n",
    "\n",
    "nComp = 1\n",
    "\n",
    "n_components = 2                                                   # build principal component model with 2 components\n",
    "pca = PCA(n_components=n_components)\n",
    "pca.fit(x)\n",
    "\n",
    "x_trans = pca.transform(x)                                         # calculate principal component scores\n",
    "\n",
    "xtrans2 = x_trans.copy()\n",
    "x_trans[:,1] = 0.0                                                 # zero / remove the 2nd principal component \n",
    "\n",
    "xtrans2[:,0] = 0\n",
    "\n",
    "xhat = pca.inverse_transform(x_trans)                             # reverse the principal component scores to standardized values\n",
    "\n",
    "xhat = np.dot(pca.inverse_transform(xhat)[:,:nComp], pca.components_[:nComp,:])\n",
    "xhat = sd*xhat + mu                                                # remove the standardization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can then plot the data points in scatter form in each of the state spaces."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    " def pc_slider(X, Y):\n",
    "    nComp = 1\n",
    "    f, ((ax201,ax202, ax203), (ax204, ax205, ax206)) = plt.subplots(2, 3,figsize=(13,8))\n",
    "    f.subplots_adjust(wspace=0.5,hspace = 0.3)\n",
    "\n",
    "    ax201.scatter(my_data_por_perm['Por'],my_data_por_perm['TOC'],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")    \n",
    "    ax201.set_title('1. Porosity vs. TOC'); \n",
    "    ax201.set_xlabel(\"Porosity\"); ax201.set_ylabel(\"TOC\")\n",
    "    ax201.set_xlim([5,25]), ax201.set_ylim([0.0,2.5])\n",
    "    features = ['Por','TOC']\n",
    "    \n",
    "    mu = np.mean(x, axis=0)\n",
    "    sd = np.std(x, axis=0)\n",
    "    stscalar = StandardScaler() \n",
    "    x_stand = stscalar.fit_transform(x)                     # standardize the data features to mean = 0, var = 1.0\n",
    "    temp = np.array([float(X), float(Y)])\n",
    "    temp=temp.reshape(-1, 2)\n",
    "    temp=s.transform(temp)\n",
    "    \n",
    "\n",
    "    ax202.scatter(x_stand[:,0],x_stand[:,1], s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax202.set_title('2. Standardized Por vs TOC'); ax202.set_xlabel('Standardized Porosity'); ax202.set_ylabel('Standardized TOC')\n",
    "    ax202.set_xlim([-3,3]), ax202.set_ylim([-3,3])\n",
    "\n",
    "    n_components = 2                                                # build principal component model with 2 components\n",
    "    pca = PCA(n_components=n_components)\n",
    "    pca.fit(x)\n",
    "\n",
    "    x_trans = pca.transform(x)                                   # calculate principal component scores\n",
    "    ax203.scatter(x_trans[:,0],x_trans[:,1],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax203.set_title('3. Principal Component Scores'); ax203.set_xlabel('PC1'); ax203.set_ylabel('PC2')\n",
    "    ax203.set_xlim([-3,3]), ax203.set_ylim([-3,3])\n",
    "    \n",
    "    x_trans[:,1] = 0.0                                              # zero / remove the 2nd principal component \n",
    "\n",
    "    ax204.scatter(x_trans[:,0],x_trans[:,1],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax204.set_title('4. Only 1st Principal Component Scores'); ax204.set_xlabel('PC1'); ax204.set_ylabel('PC2')\n",
    "    ax204.set_xlim([-3,3]), ax204.set_ylim([-3,3])\n",
    "    \n",
    "    xhat = pca.inverse_transform(x_trans)                           # reverse the principal component scores to standardized values\n",
    "    ax205.scatter(xhat[:,0],xhat[:,1],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax205.set_title('5. Reverse PCA'); \n",
    "    ax205.set_xlabel('Standardized POR'); ax205.set_ylabel('Standardized TOC')\n",
    "    ax205.set_xlim([-3,3]), ax205.set_ylim([-3,3])                      \n",
    "\n",
    "    xhat = s.inverse_transform(xhat)\n",
    "    ax206.scatter(xhat[:,0],xhat[:,1],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax206.set_title('6. De-standardized Reverse PCA');\n",
    "    ax206.set_xlabel('Porosity'); ax206.set_ylabel('TOC')\n",
    "    ax206.set_xlim([5,25]), ax206.set_ylim([0.0,2.5])\n",
    "    \n",
    "    ax201.plot(float(X),float(Y),marker = \"+\", c = 'black',markersize = 20,markeredgewidth = 3,alpha = 0.8)\n",
    "    ax202.plot(temp[:,0], temp[:,1],marker = \"+\", c = 'black',markersize = 20,markeredgewidth = 3,alpha = 0.8)\n",
    "    x_trans2= pca.transform(temp)\n",
    "    ax203.plot(x_trans2[:,0], x_trans2[:,1],marker = \"+\", c = 'black',markersize = 20,markeredgewidth = 3,alpha = 0.8)\n",
    "    x_trans2[:,1] = 0.0 \n",
    "    ax204.plot(x_trans2[:,0], x_trans2[:,1],marker = \"+\", c = 'black',markersize = 20,markeredgewidth = 3,alpha = 0.8)\n",
    "    xhat2 = pca.inverse_transform(x_trans2) \n",
    "    ax205.plot(xhat2[:,0],xhat2[:,1],marker = \"+\", c = 'black',markersize = 20,markeredgewidth = 3,alpha = 0.8)\n",
    "    xhat21 = s.inverse_transform(xhat2)\n",
    "    ax206.plot(xhat21[:,0],xhat21[:,1],marker = \"+\", c = 'black',markersize = 20,markeredgewidth = 3,alpha = 0.8)\n",
    "\n",
    "x0 = widgets.Text(value='                          Interactive PCA - Transformation and Reverse Transformation, Arham Junaid and Prof. Michael Pyrcz, The University of Texas at Austin',layout=Layout(width='950px', height='30px'))\n",
    "x1 = widgets.IntSlider(min=5, max = 25, value = 0, description = 'Porosity',orientation='horizontal')\n",
    "x2 = widgets.FloatSlider(min=0, max = 2.5, step=0.1,value = 1, description = 'TOC',orientation='horizontal')\n",
    "x4 = widgets.HBox([x1,x2],)\n",
    "uik3 = widgets.VBox([x0,x4],)\n",
    "interactive_output = widgets.interactive_output(pc_slider, {'X': x1, 'Y': x2})\n",
    "interactive_output.clear_output(wait = True)                       # reduce flickering by delaying plot updating\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Interactive Datum Projection with PCA \n",
    "\n",
    "#### Arham Junaid, SURI Student, Michael Pyrcz, Associate Professor, University of Texas at Austin \n",
    "\n",
    "Move around a datum in original feature space and observe its location over all steps of PCA forward and reverse transformation, including standardization.\n",
    "\n",
    "### The Inputs\n",
    "\n",
    "* **Porosity (%), TOC (total organic carbon %)**: the new datum's values in the original features, prior to standardization/projection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "88ca26c3a35e4951be02e26c76b3a734",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(Text(value='                          Interactive PCA - Transformation and Reverse Transformati…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b98781d7729e4d6b916615bc1c1f31c8",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display(uik3,interactive_output)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We notice the transformation, forward and backward, as we notice the  movement of the arbitrary point. In the first graph, the blue dot can move anywhere in the 2D space while in the 6th graph, the movement of the blue point is restricted to a single direction despite returning back to the lower dimensional original space.\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "#### Interactive Workflow #3: Dimensionality Reduction\n",
    "\n",
    "PCA is all about dimensionality reduction. We can see this from the graphs detailed below and how analysis in reduced dimensions allows for a more compact visualization based on the calculation of the Principal Component scores. \n",
    "\n",
    "This is done by converting our data set into Principal Component scores and retaining *p* Principal Component scores. Here, you may choose your 2 variables to calculate your 2 Principal Component scores.\n",
    "\n",
    "The following can be seen from the output below:\n",
    "1. Visual Distribution of the 2 variables\n",
    "2. Descriptive statistics of the original and transformed data set\n",
    "3. The covariance matrix and the matrix displaying variance explained by each PC score\n",
    "4. Cross plots looking the same after PCA is run indicating the method is working correctly\n",
    "5. The transformation of the data into reduced dimensional space\n",
    "6. The variance explained statistics for each PC score  \n",
    "7. Total variance explained of the 2 selected variables based on the number of PC scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6d3bd9d05e184b6781f8f5bc4fc4b840",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Text(value='                                     Interactive PCA - Dimensionality Reduction, Arham Junaid and …"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "var_por = np.var(my_data_por_perm['Por'])\n",
    "var_por_hat = np.var(xhat[:,0])\n",
    "var_logperm = np.var(my_data_por_perm['TOC'])\n",
    "var_logperm_hat = np.var(xhat[:,1])\n",
    "\n",
    "\n",
    "def firstvariable(feature1=\"Por\",\n",
    "                 feature2=\"LogPerm\"):\n",
    "    column1 = feature1; column2 = feature2\n",
    "    my_data_por_perm = df[[column1,column2]]                \n",
    "    my_data_por_perm =my_data_por_perm.iloc[0:100]\n",
    "    \n",
    "    print(\"1: Visual Distribution\")\n",
    "    \n",
    "    f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)\n",
    "    ax1.hist(my_data_por_perm[column1], alpha = 0.2, color = 'red', edgecolor = 'black', bins=20)\n",
    "    ax1.set_title(column1)\n",
    "    ax2.hist(my_data_por_perm[column2], alpha = 0.2, color = 'red', edgecolor = 'black', bins=20)\n",
    "    ax2.set_title(column2)\n",
    "    plt.show()\n",
    "    \n",
    "\n",
    "    features = [column1,column2]\n",
    "    x = my_data_por_perm.loc[:,features].values\n",
    "    mu = np.mean(x, axis=0)\n",
    "    sd = np.std(x, axis=0)\n",
    "    x = StandardScaler().fit_transform(x)                     # standardize the data features to mean = 0, var = 1.0\n",
    "    \n",
    "    print(\"2: Original and Transformed Statistics\")\n",
    "    print(\" \")\n",
    "    print(\"Original Mean \"+column1+' = ', np.round(mu[0],2), ', Original Mean '+column2+' = ', np.round(mu[1],2)) \n",
    "    print(\"Original StDev \"+column1+' = ', np.round(sd[0],2), ', Original StDev '+column2+' = ', np.round(sd[1],2)) \n",
    "    print('Mean Transformed '+column1+' = ',np.round(np.mean(x[:,0]),2),', Mean Transformed '+column2+' = ',np.round(np.mean(x[:,1]),2))\n",
    "    print('Variance Transformed '+column1+' = ',np.round(np.var(x[:,0]),2),', Variance Transformed '+column2+' = ',np.var(x[:,1]))\n",
    "    \n",
    "\n",
    "    n_components = 2\n",
    "    pca = PCA(n_components=n_components)\n",
    "    pca.fit(x)\n",
    "    print(\" \")\n",
    "    print(\"3: Covariance and Variance Explained Matrices\")\n",
    "    print(\" \")\n",
    "    print(np.round(pca.components_,3))\n",
    "    print('Variance explained by PC1 and PC2 =', np.round(pca.explained_variance_ratio_,3))\n",
    "    print(\" \")\n",
    "    print(\"4: Original and PCA Cross-plots\")\n",
    "    \n",
    "    \n",
    "    f, (ax101, ax102, ax103) = plt.subplots(1, 3,figsize=(12,2.7))\n",
    "    f.subplots_adjust(wspace=0.7)\n",
    "\n",
    "    ax101.scatter(x[:,0],x[:,1], s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax101.set_title('Standardized '+column2+' vs. '+column1); ax101.set_xlabel('Standardized '+column1); ax101.set_ylabel('Standardized '+column2)\n",
    "\n",
    "    x_trans = pca.transform(x)                                # calculate the principal component scores\n",
    "    ax102.scatter(x_trans[:,0],x_trans[:,1],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax102.set_title('Principal Component Scores'); ax102.set_xlabel('PC1'); ax102.set_ylabel('PC2')\n",
    "\n",
    "    x_reverse = pca.inverse_transform(x_trans)                        # reverse the principal component scores to standardized values\n",
    "    ax103.scatter(x_reverse[:,0],x_reverse[:,1],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax103.set_title('Reverse PCA'); ax103.set_xlabel('Standardized '+column1); ax103.set_ylabel('Standardized '+column2)\n",
    "    plt.show()\n",
    "    \n",
    "    nComp = 1\n",
    "    \n",
    "   \n",
    "    print(\"5: PCA State Space Transformation\")\n",
    "\n",
    "    mu = np.mean(x, axis=0)\n",
    "    sd = np.std(x, axis=0)\n",
    "    x_stand = StandardScaler().fit_transform(x)               # standardize the data features to mean = 0, var = 1.0\n",
    "\n",
    "\n",
    "    n_components = 2                                          # build principal component model with 2 components\n",
    "    pca = PCA(n_components=n_components)\n",
    "    pca.fit(x)\n",
    "\n",
    "    x_trans = pca.transform(x)                                # calculate principal component scores\n",
    "\n",
    "    x_trans[:,1] = 0.0                                        # zero / remove the 2nd principal component \n",
    "\n",
    "    xhat = pca.inverse_transform(x_trans)                     # reverse the principal component scores to standardized values\n",
    "\n",
    "    xhat = np.dot(pca.inverse_transform(x)[:,:nComp], pca.components_[:nComp,:])\n",
    "    xhat = sd*xhat + mu                                       # remove the standardization\n",
    "     \n",
    "    f, (ax201, ax206) = plt.subplots(1, 2,figsize=(10,3))\n",
    "    f.subplots_adjust(wspace=0.5,hspace = 0.3)\n",
    "    \n",
    "    ax201.scatter(my_data_por_perm[column1],my_data_por_perm[column2],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax201.set_title(column2+' vs. '+column1); ax201.set_xlabel(column1); ax201.set_ylabel(column2)\n",
    "\n",
    "    ax206.scatter(xhat[:,0],xhat[:,1],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    ax206.set_title('De-standardized Reverse PCA'); ax206.set_xlabel(column1); ax206.set_ylabel(column2)\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "    var_por = np.var(my_data_por_perm[column1]); var_por_hat = np.var(xhat[:,0]);\n",
    "    var_logperm = np.var(my_data_por_perm[column2]); var_logperm_hat = np.var(xhat[:,1]);\n",
    "    #print('Variance '+column1+' = ',np.round(var_por,3),', Variance Reduced Dimensional '+column1+' =',np.round(var_por_hat,3),'Fraction = ',np.round(var_por_hat/var_por,3))\n",
    "    #print('Variance '+column2+' =',np.round(var_por,3),', Variance Reduced Dimensional '+column2+' =',np.round(var_logperm_hat,3),'Fraction = ',np.round(var_logperm_hat/var_logperm,3))\n",
    "\n",
    "    global my_data_f7\n",
    "    my_data_f7=df.copy(deep=True)\n",
    "    \n",
    "    np.set_printoptions(suppress=True)\n",
    "    features = ['Por','LogPerm','AI','Brittle','TOC','VR',\"Production\"]\n",
    "    x_f7 = my_data_f7.loc[:,features].values\n",
    "    mu_f7 = np.mean(x_f7, axis=0)\n",
    "    sd_f7 = np.std(x_f7, axis=0)\n",
    "    x_f7 = StandardScaler().fit_transform(x_f7)\n",
    "\n",
    "    #print(\"Original Means = \", features[:], np.round(mu_f7[:],2)) \n",
    "    #print(\"Original StDevs = \", features[:],np.round(sd_f7[:],2)) \n",
    "    #print('Mean Transformed = ',features[:],np.round(x.mean(axis=0),2))\n",
    "    #print('Variance Transformed = ',features[:],np.round(x.var(axis=0),2))\n",
    "    \n",
    "    print(\"6: Variance Explained by PC Score\")\n",
    "    n_components = 7\n",
    "    pca_f7 = PCA(n_components=n_components)\n",
    "    pca_f7.fit(x_f7)\n",
    "    print('\\n\\nVariance explained by PC1 thru PC7 =', np.round(pca_f7.explained_variance_ratio_,3))\n",
    "    fig5 = plt.figure(figsize=(2,2))\n",
    "    ax = fig5.add_axes([0,0,1,1])\n",
    "    langs = ['PC1', 'PC2', 'PC3', 'PC4', 'PC5', 'PC6', 'PC7']\n",
    "    ax.bar(langs,np.round(pca_f7.explained_variance_ratio_,3))\n",
    "    ax.set_title('Variance Explained by Principal Component'); ax.set_xlabel(\"Principal Component\"); ax.set_ylabel(\"Fraction of Variance\")\n",
    "    \n",
    "    nComp=7\n",
    "    x_hat_dim=[]\n",
    "    while nComp >=1: \n",
    "        temp_xhat_dim = np.dot(pca_f7.transform(x_f7)[:,:nComp], pca_f7.components_[:nComp,:])\n",
    "        temp_xhat_dim= sd_f7*temp_xhat_dim + mu_f7\n",
    "        nComp-=1\n",
    "        x_hat_dim.append(temp_xhat_dim)\n",
    "\n",
    "\n",
    "    f, axes2 = plt.subplots(1, 8, figsize=(20,20))\n",
    "    f.subplots_adjust(wspace=0.7)\n",
    "    columns=['Std. Porosity','Std. Log[Perm.]','Std. Acoustic Imped.','Std. Brittleness','Std. Total Organic C', 'Std. Vit. Reflectance', 'Std. Production']\n",
    "    axes2[0].scatter(my_data_f7[column1],my_data_f7[column2],s=None, c=\"red\",marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "    axes2[0].set_title('Original Data'); axes2[0].set_xlabel(column1); axes2[0].set_ylabel(column2)\n",
    "    axes2[0].set_ylim(0.0,3.0); axes2[0].set_xlim(8,22); axes2[0].set_aspect(4.0); \n",
    "    i=1\n",
    "    title=['7 Principal Component','6 Principal Components', '5 Principal Components','4 Principal Components', '3 Principal Components', '2 Principal Components', '1 Principal Components' ]\n",
    "    while i<len(axes2):\n",
    "           axes2[i].scatter(x_hat_dim[i-1][:,0],x_hat_dim[i-1][:,4],s=None, c=\"red\", marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=0.2, linewidths=1.0, edgecolors=\"black\")\n",
    "           axes2[i].set_title(title[i-1]); axes2[i].set_xlabel(column1); axes2[i].set_ylabel(column2)\n",
    "           axes2[i].set_ylim(0.0,3.0); axes2[i].set_xlim(8,22); axes2[i].set_aspect(4.0)\n",
    "           i+=1\n",
    "    plt.show()\n",
    "    \n",
    "    print(\"7: Total Variance of Chosen Features Explained by PC Score\")\n",
    "    print(\" \")\n",
    "    \n",
    "    i=len(x_hat_dim)-1\n",
    "    while i>=0:\n",
    "        print(title[i]+': Variance '+column1+' = ',np.round(np.var(x_hat_dim[i][:,0])/(sd_f7[0]*sd_f7[0]),2),' Variance '+column2+' = ',np.round(np.var(x_hat_dim[i][:,4])/(sd_f7[4]*sd_f7[4]),2))\n",
    "        i-=1\n",
    "\n",
    "    global df_dim\n",
    "    df_dim=[]\n",
    "    i=len(x_hat_dim)-1\n",
    "    while i>=0:\n",
    "        df_1d = pd.DataFrame(data=x_hat_dim[i],columns=features)  \n",
    "        i-=1\n",
    "        df_dim.append(df_1d)\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "x0 = widgets.Text(value='                                     Interactive PCA - Dimensionality Reduction, Arham Junaid and Dr. Michael Pyrcz, The University of Texas at Austin',layout=Layout(width='950px', height='30px'))\n",
    "display(x0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Interactive Full PCA Workflow\n",
    "\n",
    "#### Arham Junaid, SURI Student, Michael Pyrcz, Associate Professor, University of Texas at Austin \n",
    "\n",
    "Select two features from the dataset and perform a complete PCA workflow on these features.\n",
    "\n",
    "### The Inputs\n",
    "\n",
    "* **Feature1, Feature2**: the 2 features to apply to a complete PCA workflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "df9a7aab89084059bd29c7dca76c422d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(Dropdown(description='feature1', options=('Por', 'LogPerm', 'AI', 'Brittle', 'TOC', 'VR'…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<function __main__.firstvariable(feature1='Por', feature2='LogPerm')>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "interact(firstvariable,feature1=[\"Por\", \"LogPerm\",\"AI\", \"Brittle\",\"TOC\",\"VR\"],feature2=[\"Por\", \"LogPerm\",\"AI\", \"Brittle\",\"TOC\",\"VR\"], continous_update=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Observations:\n",
    "* You can see from the bar graph the proportion of the variance of the data which each principal component explains.\n",
    "\n",
    "* Moreover, you can see how the bivariate relationship of the 2 variables improves as more principal components are included in your analysis. \n",
    "\n",
    "* It is interesting to note however that the first principal component alone is able to describe a large percentage of the variance of that variable. For example, the first principal component captures 88% of the Porosity variance and 68% of the Permeability variance of the data set.\n",
    "\n",
    "\n",
    "#### Interactive Workflow #4: Variance Explained\n",
    "As can be seen from the data display above, the more principal components we include, the greater the resemblance of your original data. \n",
    "* That being said, even the first 2 principle components can tell us a significant amount in relation to the 2 variables and their variance. \n",
    "* From the interaction below, the number of principal components can be chosen, and the corresponding overall variance of the data set can be explained. \n",
    "* What isn’t explained is the variance lost, a percentage that is in the minority after selecting a mere 2 principal components alone.\n",
    "\n",
    "Let's start of with a reminder of the original matrix scatter plot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 187520 characters]",
      "text/plain": [
       "<Figure size 600x400 with 49 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "pd_plot.scatter_matrix(my_data_f7.drop('Prod2Scaled',axis=1), alpha = 0.1,      # pandas matrix scatter plot\n",
    "figsize=(6, 4),color = 'black', hist_kwds={'color':['grey']})\n",
    "features = ['Por','LogPerm','AI','Brittle','TOC','VR',\"Production\"]\n",
    "x_f7 = my_data_f7.loc[:,features].values\n",
    "plt.suptitle('Original Data')\n",
    "x_f7 = StandardScaler().fit_transform(x_f7)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we can see how the number of principle component scores affects the matrix scatter plot and the proportion of variance explained."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "9827b199db894ebabc8306c30e4b4f08",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Text(value='                                     Interactive PCA - Variance Explained, Arham Junaid and Dr. Mi…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6465e9eaf3b24618864e6bdad494c9fe",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(IntSlider(value=4, description='PCs', max=7, min=1), Output()), _dom_classes=('widget-in…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def pc_slider(PCs):\n",
    "    pd_plot.scatter_matrix(df_dim[PCs-1], alpha = 0.1,                         # pandas matrix scatter plot\n",
    "    figsize=(5, 5),color = 'black', hist_kwds={'color':['grey']})\n",
    "    plt.suptitle(str(PCs)+' Principle Components')\n",
    "    n_components = PCs\n",
    "    pca_f7 = PCA(n_components=n_components)\n",
    "    pca_f7.fit(x_f7)\n",
    "    labels = 'Variance Explained', 'Variance Missing'\n",
    "    sizes = []\n",
    "    sizes.append(sum(np.round(pca_f7.explained_variance_ratio_,3)))\n",
    "    sizes.append(1-sum(np.round(pca_f7.explained_variance_ratio_,3)))\n",
    "    fig1, ax1 = plt.subplots(figsize=(3,3))\n",
    "    \n",
    "    n = ax1.pie(sizes, autopct='%1.2f%%',colors = ['red','blue'],shadow=True,startangle=90)\n",
    "    #ax1.legend(sizes, labels=labels,loc='lower right')\n",
    "    ax1.set_title('Variance for Arbitrary Feature Projection Components')\n",
    "    n[0][0].set_alpha(0.5); n[0][1].set_alpha(0.5)\n",
    "    \n",
    "    ax1.axis('equal')                                                          # Equal aspect ratio ensures that pie is drawn as a circle.\n",
    "x0 = widgets.Text(value='                                     Interactive PCA - Variance Explained, Arham Junaid and Dr. Michael Pyrcz, The University of Texas at Austin',layout=Layout(width='950px', height='30px'))\n",
    "display(x0)\n",
    "_=interact(pc_slider,PCs=(1,7), continuous_update=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Comments\n",
    "This is an interactive workflow displaying the key aspects of Principal Components. Appreciation to **Arham Junaid** for writing this code and providing this documentation as part of the SURI program at The University of Texas at Austin.\n",
    "For more about in-depth workflows on PCA, check out INSERT LINK HERE the YouTube video associated with this interactive workflow.\n",
    "\n",
    "If you want to learn more about data analytics and machine learning in Python, The Texas Center for Geostatistics has many other demonstrations on the basics of working with DataFrames, ndarrays, univariate statistics, plotting data, declustering, data transformations, trend modeling and many other workflows available [here](https://github.com/GeostatsGuy/PythonNumericalDemos), along with a package for geostatistics in Python called [GeostatsPy](https://github.com/GeostatsGuy/GeostatsPy). \n",
    "\n",
    "We hope this was helpful.\n",
    "\n",
    "*Arham and Michael*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### More on Arham Junaid:\n",
    "Arham is a world citizen who has resided in 5 countries and has spent time in various industries including Emergency Services, the Automotive industry and the Oil & Gas industry. He is currently pursuing a Mechanical Engineering degree and continues to seek experiences which combine his technical expertise with his leadership and business passion. Check out his LinkedIn below:\n",
    "#### [LinkedIn](https://www.linkedin.com/in/arhamjunaid)\n",
    "\n",
    "#### More on Michael Pyrcz and the Texas Center for Data Analytics and Geostatistics:\n",
    "\n",
    "##### Michael Pyrcz, Associate Professor, University of Texas at Austin\n",
    " \n",
    "*Novel Data Analytics, Geostatistics and Machine Learning Subsurface Solutions*\n",
    "    \n",
    "With over 17 years of experience in subsurface consulting, research and development, Michael has returned to academia driven by his passion for teaching and enthusiasm for enhancing engineers' and geoscientists' impact in subsurface resource development.\n",
    "    \n",
    "For more about Michael check out these links,\n",
    "    \n",
    "#### [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig)  | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1),\n",
    "    \n",
    "   #### Want to Work Together?\n",
    "   \n",
    "   I hope this content is helpful to those that want to learn more about subsurface modeling, data analytics and machine learning. Students and working professionals are welcome to participate,\n",
    "    \n",
    "   * Want to invite me to visit your company for training, mentoring, project review, workflow design and / or consulting? I'd be happy to drop by and work with you!\n",
    "    \n",
    "   * Interested in partnering, supporting my graduate student research or my Subsurface Data Analytics and Machine Learning consortium (co-PIs including Profs. Foster, Torres-Verdin and van Oort)? My research combines data analytics, stochastic modeling and machine learning theory with practice to develop novel methods and workflows to add value. We are solving challenging subsurface problems!\n",
    "   \n",
    "   * I can be reached at mpyrcz@austin.utexas.edu.\n",
    "   \n",
    "I'm always happy to discuss,\n",
    "   \n",
    "*Michael*\n",
    "  \n",
    "Michael Pyrcz, Ph.D., P.Eng. Associate Professor The Hildebrand Department of Petroleum and Geosystems Engineering, Bureau of Economic Geology, The Jackson School of Geosciences, The University of Texas at Austin\n",
    "    \n",
    "#### More Resources Available at: [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig)  | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1)\n",
    "   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "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.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
