audit-labs/tutorials

Learn how to perform data analysis, scripting, automation, and more!

clone: git clone https://gitbay.org/audit-labs/tutorials.git

8e4ddbe217639aca48230d90d5d62043acec3fc1

unsigned

author: Christian Cleberg <hello@cleberg.net> · 2025-12-24T01:14:09Z

update .gitignore
 .../basic_data_analysis-checkpoint.ipynb           | 720 ---------------------
 .../racf_access_analysis-checkpoint.ipynb          | 526 ---------------
 2 files changed, 1246 deletions(-)

diff --git a/notebooks/.ipynb_checkpoints/basic_data_analysis-checkpoint.ipynb b/notebooks/.ipynb_checkpoints/basic_data_analysis-checkpoint.ipynb
deleted file mode 100644
index 7eaeb5d..0000000
--- a/notebooks/.ipynb_checkpoints/basic_data_analysis-checkpoint.ipynb
+++ /dev/null
@@ -1,720 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "markdown",
-   "id": "2bc817b1",
-   "metadata": {},
-   "source": [
-    "\n",
-    "# Basic Data Analysis & Visualization\n",
-    "\n",
-    "This notebook demonstrates how to load a sample dataset, perform quick exploratory analysis, group and pivot the data, and create visualizations.\n",
-    "\n",
-    "We’re using a CSV file from: https://sample-files.com/downloads/data/csv/basic-data.csv\n",
-    "    "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "a92fdfd1",
-   "metadata": {},
-   "source": [
-    "\n",
-    "## Install Dependencies\n",
-    "\n",
-    "If you haven't installed the required libraries, run:\n",
-    "\n",
-    "```bash\n",
-    "pip install pandas matplotlib seaborn\n",
-    "```\n",
-    "    "
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "id": "b5d7308a",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Collecting pandas\n",
-      "  Downloading pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl.metadata (91 kB)\n",
-      "Collecting matplotlib\n",
-      "  Downloading matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl.metadata (52 kB)\n",
-      "Collecting seaborn\n",
-      "  Downloading seaborn-0.13.2-py3-none-any.whl.metadata (5.4 kB)\n",
-      "Collecting numpy>=1.26.0 (from pandas)\n",
-      "  Downloading numpy-2.4.0-cp314-cp314-macosx_14_0_arm64.whl.metadata (6.6 kB)\n",
-      "Requirement already satisfied: python-dateutil>=2.8.2 in /opt/homebrew/Cellar/jupyterlab/4.5.1/libexec/lib/python3.14/site-packages (from pandas) (2.9.0.post0)\n",
-      "Collecting pytz>=2020.1 (from pandas)\n",
-      "  Using cached pytz-2025.2-py2.py3-none-any.whl.metadata (22 kB)\n",
-      "Requirement already satisfied: tzdata>=2022.7 in /opt/homebrew/Cellar/jupyterlab/4.5.1/libexec/lib/python3.14/site-packages (from pandas) (2025.3)\n",
-      "Collecting contourpy>=1.0.1 (from matplotlib)\n",
-      "  Downloading contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl.metadata (5.5 kB)\n",
-      "Collecting cycler>=0.10 (from matplotlib)\n",
-      "  Downloading cycler-0.12.1-py3-none-any.whl.metadata (3.8 kB)\n",
-      "Collecting fonttools>=4.22.0 (from matplotlib)\n",
-      "  Downloading fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl.metadata (114 kB)\n",
-      "Collecting kiwisolver>=1.3.1 (from matplotlib)\n",
-      "  Downloading kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl.metadata (6.3 kB)\n",
-      "Requirement already satisfied: packaging>=20.0 in /opt/homebrew/Cellar/jupyterlab/4.5.1/libexec/lib/python3.14/site-packages (from matplotlib) (25.0)\n",
-      "Collecting pillow>=8 (from matplotlib)\n",
-      "  Downloading pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl.metadata (8.8 kB)\n",
-      "Collecting pyparsing>=3 (from matplotlib)\n",
-      "  Downloading pyparsing-3.3.1-py3-none-any.whl.metadata (5.6 kB)\n",
-      "Requirement already satisfied: six>=1.5 in /opt/homebrew/Cellar/jupyterlab/4.5.1/libexec/lib/python3.14/site-packages (from python-dateutil>=2.8.2->pandas) (1.17.0)\n",
-      "Downloading pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl (10.8 MB)\n",
-      "\u001b[2K   \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.8/10.8 MB\u001b[0m \u001b[31m5.0 MB/s\u001b[0m  \u001b[33m0:00:02\u001b[0m.9 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m:02\u001b[0m\n",
-      "\u001b[?25hDownloading matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl (8.2 MB)\n",
-      "\u001b[2K   \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m8.2/8.2 MB\u001b[0m \u001b[31m6.5 MB/s\u001b[0m  \u001b[33m0:00:01\u001b[0mm \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n",
-      "\u001b[?25hDownloading seaborn-0.13.2-py3-none-any.whl (294 kB)\n",
-      "Downloading contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl (273 kB)\n",
-      "Downloading cycler-0.12.1-py3-none-any.whl (8.3 kB)\n",
-      "Downloading fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl (2.8 MB)\n",
-      "\u001b[2K   \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.8/2.8 MB\u001b[0m \u001b[31m6.9 MB/s\u001b[0m  \u001b[33m0:00:00\u001b[0m7.6 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n",
-      "\u001b[?25hDownloading kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl (64 kB)\n",
-      "Downloading numpy-2.4.0-cp314-cp314-macosx_14_0_arm64.whl (5.2 MB)\n",
-      "\u001b[2K   \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.2/5.2 MB\u001b[0m \u001b[31m7.6 MB/s\u001b[0m  \u001b[33m0:00:00\u001b[0m7.8 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n",
-      "\u001b[?25hDownloading pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl (4.7 MB)\n",
-      "\u001b[2K   \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.7/4.7 MB\u001b[0m \u001b[31m7.9 MB/s\u001b[0m  \u001b[33m0:00:00\u001b[0m7.9 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n",
-      "\u001b[?25hDownloading pyparsing-3.3.1-py3-none-any.whl (121 kB)\n",
-      "Using cached pytz-2025.2-py2.py3-none-any.whl (509 kB)\n",
-      "Installing collected packages: pytz, pyparsing, pillow, numpy, kiwisolver, fonttools, cycler, pandas, contourpy, matplotlib, seaborn\n",
-      "\u001b[2K   \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11/11\u001b[0m [seaborn]━\u001b[0m \u001b[32m10/11\u001b[0m [seaborn]atplotlib]\n",
-      "\u001b[1A\u001b[2KSuccessfully installed contourpy-1.3.3 cycler-0.12.1 fonttools-4.61.1 kiwisolver-1.4.9 matplotlib-3.10.8 numpy-2.4.0 pandas-2.3.3 pillow-12.0.0 pyparsing-3.3.1 pytz-2025.2 seaborn-0.13.2\n",
-      "Note: you may need to restart the kernel to use updated packages.\n"
-     ]
-    }
-   ],
-   "source": [
-    "pip install pandas matplotlib seaborn"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "id": "0632140a",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Matplotlib is building the font cache; this may take a moment.\n"
-     ]
-    }
-   ],
-   "source": [
-    "import pandas as pd\n",
-    "import matplotlib.pyplot as plt\n",
-    "import seaborn as sns\n",
-    "\n",
-    "# Set plot style\n",
-    "sns.set(style=\"whitegrid\")"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "d326b5b6",
-   "metadata": {},
-   "source": [
-    "## Load Dataset"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "id": "5d5de24b",
-   "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>ID</th>\n",
-       "      <th>Name</th>\n",
-       "      <th>Age</th>\n",
-       "      <th>Country</th>\n",
-       "      <th>Email</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>1</td>\n",
-       "      <td>Name_1</td>\n",
-       "      <td>62</td>\n",
-       "      <td>Country_1</td>\n",
-       "      <td>email_1@example.com</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>2</td>\n",
-       "      <td>Name_2</td>\n",
-       "      <td>48</td>\n",
-       "      <td>Country_2</td>\n",
-       "      <td>email_2@example.com</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>3</td>\n",
-       "      <td>Name_3</td>\n",
-       "      <td>61</td>\n",
-       "      <td>Country_3</td>\n",
-       "      <td>email_3@example.com</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>4</td>\n",
-       "      <td>Name_4</td>\n",
-       "      <td>32</td>\n",
-       "      <td>Country_4</td>\n",
-       "      <td>email_4@example.com</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>5</td>\n",
-       "      <td>Name_5</td>\n",
-       "      <td>69</td>\n",
-       "      <td>Country_5</td>\n",
-       "      <td>email_5@example.com</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "   ID    Name  Age    Country                Email\n",
-       "0   1  Name_1   62  Country_1  email_1@example.com\n",
-       "1   2  Name_2   48  Country_2  email_2@example.com\n",
-       "2   3  Name_3   61  Country_3  email_3@example.com\n",
-       "3   4  Name_4   32  Country_4  email_4@example.com\n",
-       "4   5  Name_5   69  Country_5  email_5@example.com"
-      ]
-     },
-     "execution_count": 3,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "# Load the dataset from URL\n",
-    "url = \"https://sample-files.com/downloads/data/csv/basic-data.csv\"\n",
-    "df = pd.read_csv(url, skiprows=1)\n",
-    "df.columns = df.columns.str.strip()\n",
-    "\n",
-    "# Preview the data\n",
-    "df.head()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "e7f7c2e7",
-   "metadata": {},
-   "source": [
-    "## Basic Exploration"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "id": "aca7309e",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "(100, 5)\n"
-     ]
-    },
-    {
-     "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>ID</th>\n",
-       "      <th>Name</th>\n",
-       "      <th>Age</th>\n",
-       "      <th>Country</th>\n",
-       "      <th>Email</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>count</th>\n",
-       "      <td>100.000000</td>\n",
-       "      <td>100</td>\n",
-       "      <td>100.000000</td>\n",
-       "      <td>100</td>\n",
-       "      <td>100</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>unique</th>\n",
-       "      <td>NaN</td>\n",
-       "      <td>100</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>10</td>\n",
-       "      <td>100</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>top</th>\n",
-       "      <td>NaN</td>\n",
-       "      <td>Name_1</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>Country_1</td>\n",
-       "      <td>email_1@example.com</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>freq</th>\n",
-       "      <td>NaN</td>\n",
-       "      <td>1</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>10</td>\n",
-       "      <td>1</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>mean</th>\n",
-       "      <td>50.500000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>44.530000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>NaN</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>std</th>\n",
-       "      <td>29.011492</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>15.190012</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>NaN</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>min</th>\n",
-       "      <td>1.000000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>18.000000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>NaN</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>25%</th>\n",
-       "      <td>25.750000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>32.000000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>NaN</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>50%</th>\n",
-       "      <td>50.500000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>43.500000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>NaN</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>75%</th>\n",
-       "      <td>75.250000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>59.250000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>NaN</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>max</th>\n",
-       "      <td>100.000000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>69.000000</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>NaN</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "                ID    Name         Age    Country                Email\n",
-       "count   100.000000     100  100.000000        100                  100\n",
-       "unique         NaN     100         NaN         10                  100\n",
-       "top            NaN  Name_1         NaN  Country_1  email_1@example.com\n",
-       "freq           NaN       1         NaN         10                    1\n",
-       "mean     50.500000     NaN   44.530000        NaN                  NaN\n",
-       "std      29.011492     NaN   15.190012        NaN                  NaN\n",
-       "min       1.000000     NaN   18.000000        NaN                  NaN\n",
-       "25%      25.750000     NaN   32.000000        NaN                  NaN\n",
-       "50%      50.500000     NaN   43.500000        NaN                  NaN\n",
-       "75%      75.250000     NaN   59.250000        NaN                  NaN\n",
-       "max     100.000000     NaN   69.000000        NaN                  NaN"
-      ]
-     },
-     "execution_count": 4,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "# Check shape and summary stats\n",
-    "print(df.shape)\n",
-    "df.describe(include=\"all\")"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 5,
-   "id": "e775e42f",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "     ID      Name  Age    Country                  Email\n",
-      "0     1    Name_1   62  Country_1    email_1@example.com\n",
-      "1     2    Name_2   48  Country_2    email_2@example.com\n",
-      "2     3    Name_3   61  Country_3    email_3@example.com\n",
-      "3     4    Name_4   32  Country_4    email_4@example.com\n",
-      "4     5    Name_5   69  Country_5    email_5@example.com\n",
-      "..  ...       ...  ...        ...                    ...\n",
-      "95   96   Name_96   60  Country_6   email_96@example.com\n",
-      "96   97   Name_97   26  Country_7   email_97@example.com\n",
-      "97   98   Name_98   52  Country_8   email_98@example.com\n",
-      "98   99   Name_99   24  Country_9   email_99@example.com\n",
-      "99  100  Name_100   55  Country_0  email_100@example.com\n",
-      "\n",
-      "[100 rows x 5 columns]\n"
-     ]
-    }
-   ],
-   "source": [
-    "print(df)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "dc10be72",
-   "metadata": {},
-   "source": [
-    "## Grouping and Pivoting Data"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 6,
-   "id": "f87ea8af",
-   "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>Country</th>\n",
-       "      <th>RecordCount</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>Country_1</td>\n",
-       "      <td>10</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>Country_2</td>\n",
-       "      <td>10</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>Country_3</td>\n",
-       "      <td>10</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>Country_4</td>\n",
-       "      <td>10</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>Country_5</td>\n",
-       "      <td>10</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "     Country  RecordCount\n",
-       "0  Country_1           10\n",
-       "1  Country_2           10\n",
-       "2  Country_3           10\n",
-       "3  Country_4           10\n",
-       "4  Country_5           10"
-      ]
-     },
-     "execution_count": 6,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "# Example: Group by 'Country' and count number of records\n",
-    "country_counts = df[\"Country\"].value_counts().reset_index()\n",
-    "country_counts.columns = [\"Country\", \"RecordCount\"]\n",
-    "country_counts.head()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "f156d6de",
-   "metadata": {},
-   "source": [
-    "## Visualizing Record Counts by Country"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 7,
-   "id": "d644fc06",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "/var/folders/z_/x3_6fwb174s0c7wcsd813s6r0000gn/T/ipykernel_10080/1795714619.py:3: FutureWarning: \n",
-      "\n",
-      "Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.\n",
-      "\n",
-      "  sns.barplot(data=country_counts, x=\"Country\", y=\"RecordCount\", palette=\"viridis\")\n"
-     ]
-    },
-    {
-     "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA00AAAJUCAYAAADJrc3LAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAASopJREFUeJzt3QeYVOXZP+CXKiCiiIrGimLD2AV7sGvsvcZeY8OgQbFhrKh8ig0/rNhb7DG2iEZjxxg1ihoU7NgoIqC0+V/P+f6z2cXlwC7L7uzOfV/Xsrszs7NnH94zc37nLadZoVAoJAAAAKrVvPqbAQAAEJoAAABmQ08TAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AUIlrvs+a2gDlSmgCKAEHHnhgWnnllat8rLLKKmmdddZJu+++e3r44YdTqfv888+z7X7ggQdm+9ivv/46XXLJJWm77bZLa665Ztpkk03SMccck4YNG5Ya0jPPPJNOPfXU3MecdtppaYsttphn2/Dzzz+nIUOGpD322COtu+66qUePHmnfffdNDz30UIOGlv/85z9pv/32a7DfD9CQWjbobwegQrdu3VK/fv0qvp8+fXoaPXp0dgDdp0+ftNBCC6WePXs2+oq98cYb6bjjjksdO3ZMBx10UOrSpUsaN25cuueee7LweNFFF6Vdd921QbYtat2Qvvvuu3TEEUekr776KqvFGmuskWbMmJGeffbZLKxFqDzvvPNSs2bN6n3bnnjiifTmm2/W++8FKAVCE0CJaN++fVprrbV+cftvfvObtOGGG2Y9OI09NEU4Oumkk9Jyyy2Xbr755tS2bduK+7bddtt01FFHpbPPPjvreVpkkUVSuYlergjKESCjRkWbbbZZ+tWvfpUuu+yytPnmm6ctt9yyQbcToNwYngdQ4uabb77UunXrKr0L0ftw3XXXpa233jr9+te/zgLHbbfd9oufjSFdu+22WzYELg68/+d//idNmTKl4v533nknHX744Wn99dfPhgLGELkYhlX06quvZkPu7r777uxgPR7z4osvZvc99dRTaeedd856Q+J3vP/++7P9W2J7vvnmm3T66adXCUyhefPm6ZRTTkkHHHBA+vHHHytuj9+3//77Z0PVYjtPPvnkrCem6Kqrrsq2cWZxW9xXeejg448/nk488cS09tprZ8Pe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oQkAAKB29DQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAAHUdmvr27Zs+++yzau/7+OOP0zHHHFObpwUAACg5Lef0gV9++WXF1w899FDaaqutUosWLX7xuOeffz699NJLdbeFAAAAjSE0/elPf8oCUdHxxx9f7eMKhULaeOON62brAAAAGktoOvfcc7MepAhFp59+evr973+flllmmSqPad68eerQoUNaf/3158W2AgAAlG5o6ty5c9ptt92yr5s1a5Z69uyZFl544Xm5bQAAAI0nNFUW4Sl6nN577700adKk7OuZde/evS62DwAAoPGFprfffjv16tUrjR49Ovu+GJqiByq+js/Dhw+v2y0FAABoLKHpoosuSi1btsw+L7744tlcJgAAgKaoVqHp3XffTZdddlm27Hh9iWXOr7vuuuz6ULEARaze99vf/rbefj8AAFCeatVF1KlTp2qv0TSvPPzww+mMM85IBxxwQHrsscfSjjvumHr37p3efPPNetsGAACgPNUqNO2///5p8ODB2SIQ81rMkbriiivSQQcdlIWm6GWK5c432mij9Nprr83z3w8AAJS3Wg3P++STT9JHH32UXcR2xRVXTG3atKlyfywEccstt9TJBo4cOTJ98cUXaaeddqpy+4033lgnzw8AADBPQtMqq6xS8f3MS45XtwT53ISmEL1ahx9+eLbM+VJLLZX1Nm2xxRa1es7Yvln1kkXga9u2bSpXkydPrvH/n5rVvGbqpq3V1/6prWlr2lr98R5aPzULjj0cr9VVWyuu/D1PQtNtt92W6suPP/6YfT711FOzxR9OOeWU9OSTT6Zjjz023XzzzWnDDTes8XNOnTp1lkuiR2Dq1q1bKlcRUqNR1YSa1bxm6qat1df+qa1pa9pa/fEeWj81C449HK/VZVtr3br1vAlN9alVq1bZ5+hliovqhlVXXTXrcaptaIrn7Nq1a7X3zUnSbMq6dOlSq56mclabmgV109a0tfrhda1+aha8rnld09bqh9e1uqvZiBEj5ujnaxWaYljc7F4Yn3nmmVQXOnfunH1eaaWVqtweoee5556r1XPGtrdr165Otq+pKeehibWlZuqmrZU2+6iaaWuly/6pbg3d1ub0ZE+tQlOPHj1+8QsmTpyY3nnnnfTzzz+ngw8+ONWV1VZbLc0///zprbfeSuutt17F7R9++GG2kh4AAMC8VKvQ1L9//1nOFYq5RrUZmzorsTLfEUccka655pqs12mNNdbIrtX04osvpiFDhtTZ7wEAAJjnc5pirlBcT6lv377ppJNOqrPnjSAWXWqXX355+vrrr9MKK6yQrrrqqrT++uvX2e8AAACol4Ugxo8fnw3Vq2uHHnpo9gEAAFDyoemhhx76xW3Tp09Po0ePTrfffnuVuUcAAABlF5pOO+20Wd639tprp7POOmtutgkAAKBxh6bqlhOP1fTat2+fOnToUBfbBQAA0HhD05JLLlnx9UcffZQmTJiQOnbsKDABAABNTq0XgvjLX/6SLr744vTdd99V3LbIIoukk08+Oe266651tX0AAACNLzQNHTo0/fGPf0wbbLBB6t27dxaWvvnmm/TII49ky40vtNBCabPNNqv7rQUAAGgMoenaa69N2223XXbdpMr22GOP9Ic//CENHjxYaAIAAJqE5rX5oQ8//DDttttu1d4Xt7///vtzu10AAACNNzTFog9xEdvqjBs3LrVu3XputwsAAKDxhqYNN9wwXX311dnFbCv76quv0jXXXJM23njjuto+AACAxjenKRZ/iPlL22yzTXYx21gIIlbRe/PNN9OCCy6YraAHAABQtj1Niy66aHrwwQfTgQcemCZPnpz+/e9/Z5/j+7i98nWcAAAAyvI6TZ06dcqWHQcAAGjKatTTNG3atHT77benp59+usrt06dPz1bNGzJkSJoxY0ZdbyMAAEDph6apU6emY489Nl1wwQXZ3KXKxowZk4Wl/v37p+OPPz4LUQAAAGUVmu655570yiuvpAEDBqQ+ffr8Yo7Tww8/nIWm559/Pt1///3zYlsBAABKNzQ98MAD6ZBDDkk77LDDLB+z6667pr322ivdd999dbV9AAAAjSM0ffLJJ2mDDTaY7eN69uyZRo0aNbfbBQAA0LhCU8uWLbN5TXPyuGbNms3tdgEAADSu0LTiiiumV199dbaPe+2119JSSy01t9sFAADQuELTLrvsku6666709ttvz/Ix7777brrjjjvSb3/727raPgAAgMZxcds999wz/eUvf0kHHnhg9vVmm22W9SjFUuNffPFFtmrevffem1ZeeeXsMQAAAGUVmmKe0uDBg9OFF16YLT9+5513VtxXKBSyuUyxcl7v3r1TmzZt5tX2AgAAlGZoChGGzj333HTSSSell19+OY0ePTq1aNEiLbnkktnKegsssMC821IAAIBSD01FCy+8cO71mgAAAMouND300EM1euK40C0AAEDZhKbTTjutyvfFazHFfKaZbwtCEwAAUFah6Zlnnqn4evjw4emPf/xjOvbYY7PlxRdbbLE0duzYNHTo0HTVVVeliy66aF5tLwAAQGmGpljsoeiEE07IAtORRx5ZcVvnzp3Tfvvtl6ZMmZIuvfTS1LNnz7rfWgAAgFK9uG1lH330UerWrVu19y2//PLp888/n9vtAgAAaLyhabnllkuPPvpotffFNZxWWmmlud0uAACAxrvk+HHHHZd69eqVRo0alTbffPPUsWPH9N1336WnnnoqjRgxIl1//fV1v6UAAACNJTRts8026ZprrkmDBg1KAwcOzFbQa968eVp77bXTkCFD0nrrrVf3WwoAANBYQtPLL7+cNtpoo7TFFlukn3/+OY0fPz4ttNBCqXXr1nW/hQAAAI1tTlOsnhdD8cJ8882XLTkuMAEAAE1RrUJThw4dUps2bep+awAAAJrC8Lyjjz46nX/++WnkyJFplVVWSe3atfvFY7p3714X2wcAAND4QlO/fv2yz5dffnn2uVmzZhX3xaIQ8f3w4cPrahsBAAAaV2i69dZb635LAAAAmkpo6tGjR91vCQAAQFMJTSHmM1155ZXptddeSz/88EN2gdu4PlNc+HaFFVao260EAABoTKFpxIgRad99900tWrTIrtW0yCKLpG+//TY9++yz6bnnnkv33Xef4AQAAJRvaBowYEBaaqml0m233ZYWWGCBitsnTJiQDj744GyBiKuvvroutxMAAKDxXKfp9ddfT8ccc0yVwBTi+6OOOiq7HwAAoGxDU8uWLdN8881X7X2tW7dOU6ZMmdvtAgAAaLyhafXVV0933nlndk2myuL7O+64I/3617+uq+0DAABoULWa09SrV6+03377pZ133jltt912adFFF80WgnjiiSeyVfVuvvnmut9SAACAxhKaoqfphhtuSP/zP/+TLfgQPUzNmjXLepiuv/761L1797rfUgAAgMZ0naYNNtgg3X333dn8pbhOU4cOHdK0adN+sTgEAABA2c1pmjp1aurXr1/ae++9U9u2bVPnzp3Tm2++mTbccMN08cUXpxkzZtT9lgIAADSW0HTVVVelRx55JO2www4Vt3Xr1i2dcsop6d57782G7gEAAJTt8LxHH300nXrqqWnfffetuG2hhRZKhxxySLYc+a233ppdrwkAAKAse5rGjh2bll566WrvW3755dPo0aPndrsAAAAab2iKYPTkk09We9/QoUPTsssuO7fbBQAA0HiH5x100EHptNNOS+PGjUtbbbVV6tSpUxozZkx69tln0+OPP54uuuiiut9SAACAxhKadt111zRx4sQ0aNCg9NRTT1Xc3rFjx3TWWWdl9wMAAJT1dZoOOOCAtP/++6eRI0dmPU5xnaYYtte8ea1G/AEAAJSkuUo4cVHbCE0ffPBBWnjhhdOoUaNSoVCou60DAABorD1N1157bRo8eHD66aefUrNmzdIaa6yRBg4cmK2sd9NNN2U9TwAAAGXZ03T77bdnF7g99NBDs4vZFnuXfve736XPPvssXXHFFXW9nQAAAI0nNN12223ZxWt79eqVVltttYrbe/bsmU466aRs2XEAAICyDU1ffvll6tGjR7X3xWIQ33333dxuFwAAQOMNTUsssUR68803q73v3//+d3Y/AABA2S4Eseeee2Zzmtq0aZM222yz7LZJkyalJ598MlscIuY6AQAAlG1oOvLII9Pnn3+eBgwYkH2Egw46KFsQYuedd05HH310XW8nAABA4wlNscT4ueeemw477LD0yiuvZBe3XWCBBVL37t1T165d01133ZVd/BYAAKCsQtPzzz+fHnzwwSw07bLLLtlqecstt1zF/cOGDUu77757drFboQkAACir0PTII4+kPn36pFatWqXWrVunxx9/PF155ZVp6623znqazj///PTYY4+lFi1amNMEAACUX2i65ZZb0pprrpluvPHGLDT17ds3XXPNNWnFFVfMQtJXX32VNt1003T66aenLl26zNutBgAAKLXQNGrUqHTeeeel9u3bZ98ff/zxafvtt0/HHntsmjJlSrriiivStttuOy+3FQAAoHRDUywpXvn6S0suuWS2Wl7Lli2zoXudOnWaV9sIAABQ+he3jYAU85WKil//4Q9/EJgAAIAma45D06wstthidbMlAAAATTE0xfLjAAAATVWNrtN0zjnnVCwEEcP1wllnnZXmn3/+XwSpWG0PAACgbEJT9+7dq4SlWd1W3fcAAABNPjTddtttqaGNHDky7b777lnvVnwGAAAo+TlN9WXq1KnplFNOyZY+BwAAqC+NJjRdddVVFfOpAAAA6kujCE2vv/56uueee1L//v0belMAAIAyU6PV8xrCDz/8kPr06ZPOPPPMtMQSS9TJc8ZCFbMa5hcr/7Vt2zaVq8mTJ9d4IQ81q3nN1E1bq6/9U1vT1rS1+uM9tH5qFhx7OF6rq7YWt83JJZRKPjTFMudrr7122mmnnep0ftTw4cOrvS8CU7du3VK5isU2olHVhJrVvGbqpq3V1/6prWlr2lr98R5aPzULjj0cr9VlW2vdunXjDk0PPfRQGjZsWHr00Ufr9HlbtWqVunbtWu195X6x3i5dutSqp6mc1aZmQd20NW2tfnhdq5+aBa9rXte0tfrhda3uajZixIg5+vmSDk33339/+v7779Nmm21W5fZ+/fqlv/71r+mGG26o1fPGi3q7du3qaCublnIemlhbaqZu2lpps4+qmbZWuuyf6tbQbW1OT/aUdGgaMGBA+umnn6rcts0226QTTzwx7bzzzg22XQAAQPko6dDUuXPnam/v1KnTLO8DAAAouyXHAQAAGkpJ9zRV54MPPmjoTQAAAMqIniYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAANDYQ9O4cePS2WefnX7zm9+kddZZJ+23335p2LBhDb1ZAABAGWgUoal3797pzTffTJdddlm6//7706qrrpoOP/zw9PHHHzf0pgEAAE1cyYemTz75JL344ovpnHPOSeutt17q0qVLOuuss9Jiiy2WHn300YbePAAAoIkr+dDUsWPHdN1116XVV1+94rZmzZplHz/88EODbhsAAND0tUwlrkOHDqlnz55VbnvyySezHqjTTz+9Vs9ZKBTSpEmTqr0vwljbtm1TuZo8eXJWn5pQs5rXTN20tfraP7U1bU1bqz/eQ+unZsGxh+O1umprcVu0p0Yfmmb2z3/+M/Xt2zdts802abPNNqvVc0ydOjUNHz682vsiMHXr1i2Vq5EjR2aNqibUrOY1Uzdtrb72T21NW9PW6o/30PqpWXDs4XitLtta69atm1Zo+tvf/pZOOeWUbAW9AQMG1Pp5WrVqlbp27VrtfXOSNJuymDNWm56mclabmgV109a0tfrhda1+aha8rnld09bqh9e1uqvZiBEj5ujnG01ouv3229MFF1yQtttuu3TxxRfPUSLMe1Fv165dnW5fU1HOQxNrS83UTVsrbfZRNdPWSpf9U93qy6za2pye7Cn5hSDCnXfemc4777x0wAEHZMuOz01gAgAAqImWjWH84YUXXpi23nrrdPTRR6fvvvuu4r42bdqkBRZYoEG3DwAAaNpKPjTFSnmxcMPTTz+dfVS22267pf79+zfYtgEAAE1fyYemY445JvsAAABoCI1iThMAAEBDEZoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAAEAOoQkAACCH0AQAAJBDaAIAAMghNAEAAOQQmgAAAHIITQAAADmEJgAAgBxCEwAAQA6hCQAAIIfQBAAAkENoAgAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIDGHppmzJiRrrzyyrTpppumtdZaKx155JHps88+a+jNAgAAykCjCE2DBg1Kd955ZzrvvPPS3XffnYWoI444Ik2ZMqWhNw0AAGjiSj40RTC66aab0oknnpg222yztMoqq6TLL788jR49Oj311FMNvXkAAEATV/Kh6f33308TJ05MG264YcVtHTp0SN26dUuvv/56g24bAADQ9DUrFAqFVMKiN+mEE05Ib731VmrTpk3F7b169Uo//fRTGjx4cI2e75///GeKP7lVq1azfEyzZs3S+DET0rRp01O5aNmyRVpw4QWy2tRGVrNxE9O06WVUsxYt0oILzV/rmhXrNu6HSWVXt4U6tJurtjb2x0llt392bF/7mlXUbeLENHX6jFQuWrVonjrOX/t9NGo2ZtLENG1GGbW15i3Swu3m/nVt7E/lV7eObeaurU2Y8mPZ1WyB1u3nuq1NmvpDmlEon7o1b9YitWvVYa7a2pSpY9OMwrRULpo3a5lat+o4y5pNnTo1q8s666yT+zwtU4mbPHly9rl169ZVbp9vvvnS+PHja/x8UZTKn2clAkQ5ml1d8kSAKEdzU7MQAaIczU3dIkCUo7ltaxEgytHc1C0CRDma67bWRt1qKgJEOZrbthYBohzNTd0iQJSjZrOoWdw+J/Us+dBU7F2KuU2Ve5p+/vnn1LZt2xo/39prr12n2wcAADRtJT+naYkllsg+f/PNN1Vuj+87d+7cQFsFAACUi5IPTbFaXvv27dOrr75acdsPP/yQ3nvvvdS9e/cG3TYAAKDpK/nheTGX6Xe/+10aMGBAWnjhhdOSSy6ZLr300rT44ounbbbZpqE3DwAAaOJKPjSFuEbTtGnT0plnnpmtmBc9TDfeeGPuCngAAABlseQ4AABAQyr5OU0AAAANSWgCAADIITQBAADkEJoAAAByCE0AAAA5hCYAAIAcQhMAwExckQWoTGgCoFFwEEt9GTNmTGrWrJmC14L9lKZKaAKoZz/99JOa19D555+fRo4cqW41NGPGDDWroT/84Q/p8ssvz74WAGpO2KSpatnQG0DduvXWW1OPHj3SKqusorQ1cM0116Rvvvkm/fDDD2nfffdNq6++emrXrp0azqatjR8/Pv3888/ZQUaLFi2yAwxvmPl69eqVFllkkXTCCSekhRZaSBubA/vtt1/6/vvvU58+fdSrBi688ML09ddfpx9//DEddNBBaaONNkqtWrVSwxwHHnhgev3111P37t2z772ezZlrr70220fjhNDxxx+fFl98ce8Hs/HQQw+lCRMmZPvnrrvumjp16pRat25t/5yNO+64I6vb9OnT01577ZU6duxYb69rQlMT8tFHH6UhQ4akf//73+mYY45Jyy+/fENvUqNw2GGHZUMxunXrlp3JPvnkk1Pfvn3TDjvs0NCbVtIHFhGY4o3xrbfeSh9//HEaNGiQA4w5MGnSpOxFf+GFF87q2KFDh3n/H9bIA9OUKVOyA4w4oBDM58yhhx6aHcRuscUW6bXXXstOCglM+eKE2bRp09Kf/vSn9Oc//zk7IRQ1a97coJw8hxxySBo3blxaccUV0xtvvJGGDx+e7r///uz9wP466/0zDvwXXHDB9Omnn6b77rsv/e53v0t77rmn94Qc8Z4Zr2vx/vnFF1+kBx98MDshtNNOO2XhaV4TmpqQxRZbLEvew4YNS//7v/+bjj766LTCCis09GaVtMGDB2cvXHfddVdq27Ztdtv++++fbrnlFqFpFq644oo0ceLE7KAi3hDjzTE+4gxjmzZt6vO/r1GKXuAImldffXXWsxk9Tu3bt2/ozSrZA4s4ofHkk09W3DZ16tTsda5ly5ZZ72Yc0MYQNAe2/zV06NDsIDZOosXBRVGEgKiTuv3SAQcckLWte++9Nzvo79evX3YiMk6mMfuz/lG32Cfj+OOss87KXtvihFCxp84++l/XXXdd9rp25513ZiNaokYxAiGGhI4dOzZ73au83/J/ol7RKxcBc7755svaW4w+iOO3r776Kh155JHzvG5OnzQh8YYYL/prrrlm9qIfwSle9Jm1OPvapUuXLDAV55nsvffe6bPPPsvO/vBLo0ePTmuttVZ2BjZeuOLNMGp11FFHZWfJYthevCFQ/dyS6J3bcssts/3ztttuS1dddVXFY+JAg/8Tb47zzz9/dvawWJf//Oc/qXfv3lmPwO67754uu+yybPhZBAFzT/4rAtO3335b0eaibnESLfbPqNvAgQPVrZITTzwxe82K/TECZQyfXXrppdP777+f3R8hnVnvp3HgH8cesR/G93HgHyEg9tMrr7xSW5tJHODHSe44yRh1K56MjF6np556Kt19993ZiUmqirZVDEvFMH7JJZekzTffPP3jH//IAnw8Zl4SmpqIOGB4++2306KLLpqdrYghLfGCLzjliwOLESNGZF8Xe0niIC1esByEVS/eECdPnpy9aMWLf7SxDTfcMG2yySZZ+7v99tuzF68YUsV/FXtCYr5cDKHdeOON09lnn52FzP79+6eDDz44Pf7440r2/0XvW5z9jzfJqNGHH35Y0Su3zz77pHXWWSd7o4yDsthfzT35r3gtK/bEfffdd9kJjdg3YxjVuuuum/7+979ngTN6CMq9btF2dt5552yYT3Eea5zYiKFm99xzT/Z91JH8k48xfDZev+LM//rrr5969uyZlltuufT0009nxyRxMFvuba3ySY0YYhbtKoYcxwnbON749a9/nbp27ZrVMV7vguOQVKUGUbvia1vxGKPY5v7yl79kQ5Hnad0KNBnvvPNOYeDAgYUZM2Zk3992222FHXfcsXDKKacURowY0dCbV1KKNXrllVcKvXv3Lnz11VcV9w0dOrSw2mqrFT755JMqPzNp0qRCOSvWbNSoUYXnnnsu+3rcuHGFu+66q/Dzzz9XPO6ss84qbLnllmVfr1mJfXHjjTcujBw5Mvv+vvvuK6yyyiqF3/zmN4XRo0fP8//HxuaKK64o7LbbbtnrWP/+/SvaYbj22msLW221VeH7779v0G0sNbE/brrppoU+ffoU3nvvvUK/fv0KU6ZMqbj/uuuuK2yxxRYVbZD/mj59evb58ccfL2y99daFYcOGZd9XbndUrdc+++xT2GSTTQrrr79+4dhjj61Snmhr8X7wxRdflH3Zim3o5ZdfLqy33nrZ61nR008/nR2vfffdd4X99tuvcPjhh5d9vWYWr/M9evQo9O3bt+K2yscehx12WGHvvfcuzEt6mpqQOEtx7LHHVpzNiUmFcUY2epxi7o6hev9VrFGcdT3nnHOyM4tF0V0ew4Iqz5E444wz0hNPPJHKWbFmyy67bHYWMcRwghjOGGfLYgJ1+P3vf58Nx4ghovxSzDOMoT/FYRkxTjvOakePQAwPMkQvVTlTGEOnovf30UcfzcarRzssDpeKnqhoa9HLzv+J2sT+GIvZvPDCC9l7QpzVjuG0xbrFZOoYjhY9nlRVfN3fYIMNsn002l3x9c9Z/6qiPUW94jUseoNj6GdxDlixFyDmCEdP1Lvvvlv2Ta34Hrrqqqtm829ibk4s1BLvoTGcMXqCYwW9mNP0+eefZ/uoNvd/og7x+v/HP/4xPfvss+nSSy/Nbi/21IWo4SeffJItTDWv6iY0NTHF1ZGKY9kjOMW44g8++CAb+xmrjfBf0c27wAILZF8XDyi+/PLL7I2gOKEwhra8+OKL2eoszPogI2pZHPIYwzJiOBDVi7AZITwOKCIQxEIasTz0DTfckB555BFl+/8HqcV9MoYv7rHHHtkqSZWHS0VgihBf+aRHuSvWJobMRjiKGsaQ2jipUbwvvo/g3rlz5wbe2tIU759xOYBTTjklGypVXIjE8LKqoj0VF3iIucGx8MM777yT3VdcOjtOBsWQsyWXXLLe/x9L+fU/XvvjJNm2226bzcmJRVviNS5EWI/jkphrrc39n2IdYj5wHNc+/PDD6aKLLqoytSKmDcT7aXFxjXnB6nlNVOUVpeJsbIzbjrk7SyyxRENvWskqHlAUJ7TG2YtYfjwWOYhx2REK4gDE+PaqYpJ5rJgUc5riRSvmOMUBhzfJXyq2n1hBL64Nts0222RhKU527LLLLlndYq4T/90n43UsAvgFF1yQ3fbyyy9nB2gxHyfmSkSv8EorraRkM4m2FAdhcfAQIw1iIYg4gRYHs7HaVLS5mBfGrE8ERX3idS0O0CKYxyJLVF+rsN5666Ubb7wxXXzxxemII47ITqDFpSji4H/llVdWukpibmb0OMVHiMWn4mRG9ND99a9/TUsttZTVaKsRoag4uiVWIYy6xXzgeK+4+eabs/00FtmYV5rFGL159uw0uMrLfBavl2Dpz+oV6xMLGcQLfRyoRXCKyYVxgBFnaou9KfxXXJcjDsiiPr/61a+ylafijTNqpq3NumZxIBZnsqu7TpO2Vr0YehErwMW1rpZZZpmsrd10003aWo4Il3H2f8CAAdkwvQhTcfIsVm0sDtlzImjWYtGM2E/jen4x9JhZi6HFsXhGvP7He2cc+McBbIR2bW3WYnGDWOQmTkDGcUcsflM8seE6V9WLhUXee++97KRjDGOM3qYITPP62ENoKgOVdzo74OzFjhhjs1dbbbVs6U+BKV8cdMWBWfRkxpCCmJ8TL1YO/PP3R4Gydm0tDvxjvlwMn419VFubM9HeYrXLOLgozg2zj855cIoeJ+Fy9qKnJA5oYw5TBCbvB3MmTgTFaqBxUiPmWkdbs3/O2etanEyLE9oxumVevx8ITY2EA6z6q1vMk4gJmnFWsRxfuGpas+qCeDm213L8m0uhrZVjT0lN61bd48utvdbm7535Z7S12fN+UDf7p7ZWmq9r5fOK2cgVG0GcKay80EOemUdeluMF+mpTt5gcffzxx1cciJXbRMya1qy6VaXKcdSvfXTe16zYQ1fualq36i7+W277aG32z3J77a+O94N5X7PiHPRy17wRvK4JTY3I0KFD029/+9uKq2vP6dme5557rizPWtSmbpV30nKum7ambqXa1oqPKef9M9hH1UxbK11e15rm65rQ1IjExOdYdSsmkef1HFVuSDEp85hjjklvvvlmKlc1qVtxJy33umlr6qatlTb7qJppa6XL/tlE6zZPL53LXF+VfGbHH398drXoWal81fK77roru+r0k08+WTb/E+qmZtpa6bJ/qpu2Vtrso2qmrc2a0FSCKgeft956qzBhwoSK7z/99NNCz549Cw8++OBsA9M666xTeOKJJwrlQt3UTFsrXfZPddPWSpt9VM20tXxCUwmf5Yngs9VWWxV22GGHwtChQ7PAFHr37l0499xzq7zIlXtgUjc109ZKl/1T3bS10mYfVTNtbfYsOV5CKi+VeOWVV6aPP/44bbrppumVV15Jzz//fOrSpUt2Rfe4unbv3r2zi5+tscYaVZ4jrit06aWXZhf82nbbbVM5UDc109ZKl/1T3bS10mYfVTNtbQ7NQbCinr366quF3XbbrTBixIiKHqQXXnihcNlllxVWX331bF7TmmuumfU2TZkypeIM0bPPPpvdXk49TJWpm5ppa6XL/qlu2lpps4+qmbaWT2hqYKNHj67SLf70008XevToUTjkkEMKEydOLEydOrXK47/44ovCFVdcUdhnn30KG2ywQeGHH36ouG/cuHGFYcOGFcqBuqmZtla67J/qpq2VNvuommlrNWfJ8QY0ZcqUNHDgwHTnnXdm37///vtZN/mKK66Y3n777fTdd9+lli1bZo8rLr34q1/9Kh133HHp1ltvTUsvvXQaNGhQdt+0adPSggsumNZdd93U1Kmbmmlrpcv+qW7aWmmzj6qZtlY7QlMDat26dRaCzj///GyuUsxF6tGjR+rVq1dacskl0+GHH55+/PHH7HERiooX7YrPcVu3bt3SuHHjstsiXJULdVMzba102T/VTVsrbfZRNdPWakdoamAnnHBCWnXVVdO//vWvtNJKK6WFFloorbPOOunMM89M8803X9pjjz2y4BShKIJT0dixY7OFIj7//PPsrFEMtSwn6qZm2lrpsn+qm7ZW2uyjaqat1ZzQ1AAqB5wxY8Zkw+z23HPPdPPNN6chQ4ZkPUkxzO7ss8/OzgjttddeacKECVV6k4o/d8YZZ2SPKV4ZuSlTNzXT1kqX/VPdtLXSZh9VM21t7nci6lHlRR+KizjECnjh8ssvL6y88sqFm2++ueIxr7/+emHTTTctnHjiib94rp9//rlQLtRNzbS10mX/VDdtrbTZR9VMW5t75TMRpkTO8hSvw3TjjTdm115q165dNp9pww03zOYyRY/RxRdfnH3ef//908SJE7PFItZcc81fPF/0MJUDdVMzba102T/VTVsrbfZRNdPW6kgdBC/mQPF6S2HgwIGFddZZp3DeeecVttlmm8IWW2xRuPfee7Oeo3hcLCkePU7du3cvHHfccRU/O23atLKrtbqpmbZWuuyf6qatlTb7qJppa3VHaKpncZ2lI488svDmm29W3Hb00UcXtt1224rgVLxe05VXXllxnabKL3zlSN3UTFsrXfZPddPWSpt9VM20tbknNNWjW265pbDZZpsVdt5558Knn35acXvMaaocnOKitpXNfIHbcqNuaqatlS77p7ppa6XNPqpm2lrdsHrePDTzMuA77bRTatOmTfrggw8qLmQbWrVqla6++uq0/PLLp0suuSS99NJLVX6unK7BFNRNzbS10mX/VDdtrbTZR9VMW5tH6ih8keO2224rPP7449nX48ePL2y11VaF7bffPlsZr/Kwu+hRuuSSS8py7lJ11E3NtLXSZf9UN22ttNlH1Uxbq1tC0zw2evTowqGHHlrYeOONC0OHDs1uGzt2bGHzzTcv7LTTTr8ITkXlHpzUTc20tdJl/1Q3ba202UfVTFure0LTPLoWQuUgFIs+9OrVq9CzZ8/CM888UxGcYtW8XXfdtfDSSy+V/UIP6qat1RdtTc20tdJl/1Q3ba20TS/j41yhaR6e5ansX//6V+GEE07IGlSxx2ncuHGFNdZYo9CnT595tRmNjrqpmbZWuuyf6qatlTb7qJppa/OO0DQPPPbYY4V11103G3pXWSTxI444ovCb3/ym8OKLL2a3TZgwoeyH4qmbtlbf7KNqpq2VLvunumlrpe2xMj3OtXrePLDQQgulNddcM51xxhlp2LBhFbevtdZaafvtt09ff/11Ouqoo9Krr76a2rdvn1q0aJGmT5+eyp26qZm2Vrrsn+qmrZU2+6iaaWvzWEOntqYytnNmb7/9duGwww7LxnNWTuJvvPFGoXfv3oX77ruvySTv2lA3NdPWSpf9U920tdJmH1Uzba3+NYt/5nUwa6riOkvNm/9fZ92jjz6aRo0alb788su08cYbp6233jp99tlnqX///unjjz9O/fr1S127dk0XXHBBWmSRRdK5556b/Vz0MEVPUzlRNzXT1kqX/VPdtLXSZh9VM22tYQhNdSAuSPvAAw+k9dZbL3300Udp8uTJacUVV0wDBw5Mn3/+ebrsssvS3//+9/SrX/0qzT///Nlj44K2kVebNWuWypW6qZm2Vrrsn+qmrZU2+6iaaWv1rAF6t5qUp59+OrtY7bvvvltx21133VXYeeeds2F4ccHaMWPGFF544YXsArfFIXlxezlTNzXT1kqX/VPdtLXSZh9VM22t/rWs75DWmH3//ffp22+/zYbTRU9S+PTTT9MSSyyRVlhhhTR16tSsB2n33XdP48ePT3fffXc2ZC+G5W2yySYVzxND8lq2LJ/Sq5uaaWuly/6pbtpaabOPqpm2VhqsnjeHTj/99NSrV6+06667Zh8333xzdnuEoghI8803XxaYpkyZklq3bp322GOPNHr06Gy43szKaQ6TuqmZtla67J/qpq2VNvuommlrpUNomgOHHnpotpjDYYcdlm699dZsrlIsHR523HHHLBgNHjw4+z4CU4ggtcoqq2TzmMqVuqmZtla67J/qpq2VNvuommlrpaV8xojV0lVXXZUt7DBo0KC08MILV1m5JhZyWGONNdKBBx6YbrrppjRx4sS0zz77pB9//DFdfvnlqU2bNmm11VZL5Ujd1ExbK132T3XT1kqbfVTNtLXSIzTNxnvvvZe22mqrisAUisuMx8p3EYzatm2bjjzyyHTjjTdmPVGdO3dOnTp1yr6Ox1ZeHrRcqJuaaWuly/6pbtpaabOPqpm2VnqEplmIoBOLPvzzn/9MBx98cMVtM4efsWPHpsceeyz17Nkzu1bTu+++mwWmbt26ZY+dNm1aWS36oG5qpq2VLvunumlrpc0+qmbaWukqr+6PGojAExehbd++fXr55Zcrbqsshud17NgxdenSJX399dfZ4yM8/frXv67oYSqnwBTUTc20tdJl/1Q3ba202UfVTFsrXULTLEQgiiXEl19++fTKK6+kkSNH/uIxxQvTxhLicdHaXxS3zIbkBXVTM22tdNk/1U1bK232UTXT1kpX+R3Vz6HifKXjjz8+G1t8ww03ZMP1ZjZmzJg0YcKEbDge6qat2UdLmdc1ddPWSpt9VM20tRLWABfUbXTuvffewmqrrVY44YQTCi+99FJ229SpUwtffPFF4eijjy7svffehWnTpjX0ZpYcdVMzba102T/VTVsrbfZRNdPWSkuz+Kehg1upixI9/fTTqV+/ftmFaWN1vDgbFPOVYgjeLbfckl3YNobpldOFa2dH3dRMWytd9k9109ZKm31UzbS10iI01cCXX36ZXnrppfT2229nC0CsvPLKadttt82CUrmtklcT6qZm2lrpsn+qm7ZW2uyjaqatlQahqQ7oYVK3+qKtqZu2Vtrso2qmrZUu+6e6zQ2hqRbd5cVV8yp/jbrVNW1N3eqLtqZu2lpps4+qmbbW8IQmAACAHJYcBwAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAGpwvRwAyk/Lht4AAJjZO++8k2699db0+uuvpzFjxqTFFlssbbjhhumoo45KSy+9dIMUbNCgQal169bpiCOOaJDfD0DD0dMEQEm544470r777pu+//77dPLJJ6frr78+C0uvvfZa2nPPPdP777/fINt1xRVXpMmTJzfI7wagYelpAqBkvPHGG+mCCy5IBxxwQDrjjDMqbl9//fXTVlttlXbdddd0+umnpwceeKBBtxOA8qKnCYCSceONN6YFFlgg9e7d+xf3Lbzwwum0005LW265ZZo0aVKaPn161iu10047pTXWWCNtttlmacCAAennn3+u+JkDDzww+6js1VdfTSuvvHL2OUQA69atW3rrrbfSPvvsk1ZfffW0+eabZ9tSFI8PV199dcXXV111Vdp6662z23r06JE22WSTdOaZZ2bbMmHChF8M7Vt33XX1VAE0UkITACWzyMI//vGPbO5S27Ztq33M9ttvn4477rjUrl27dPbZZ6eLLroo64G69tprs96p22+/PR177LE1XrBhxowZ6aSTTsqe/7rrrkvrrLNOuuSSS9ILL7yQ3X/PPfdkn2N4YPHr8OWXX6a///3v6fLLL099+/ZNhx56aBbannjiiSrP//DDD2fPPau/C4DSZngeACVh7NixWeBYaqmlZvvYESNGpD//+c/ZnKeY7xQ23njjbMGIPn36pOeffz717Nlzjn93hKwIW3vttVf2ffQKPf300+m5555Lm266aVprrbWy2xdffPGKr8O0adPSqaeemtZbb72K29Zee+0sJBWf65///GcaNWpU6t+/fw2qAUAp0dMEQElo0aJF9jmG3c1OLAoRdthhhyq3x/fxPMWhdzURYacoVsmL4YAxDHB2Vl111Srf77HHHmnYsGHpiy++yL5/8MEHU5cuXao8PwCNi9AEQElYcMEF0/zzz58NeZuVCDHjx4/PPsKiiy5a5f6WLVumjh07/mJO0Zxo06ZNle+bN28+R8P8YpsrKw7Di96m6Dl7/PHH0+67717j7QGgdAhNAJSMWEwheokqL+ZQ2b333ps22GCDiu+//fbbKvdPnTo1G+YXwalo5p6rOek9mhsRorbbbrssLMWcqPh9u+yyyzz9nQDMW0ITACXjsMMOS+PGjUsDBw78xX0RkG666abUtWvXbNW68Nhjj1V5THwfISnmJIX27dun0aNH/2JZ89qInqc5FQtGfPjhh+mWW25JG220UercuXOtficApcFCEACUjFhkoVevXllo+uijj7LrMkWv0X/+859sCfDogYr7VlhhhbTbbrulK6+8MlvGu3v37mn48OHZ8t9xTadYvCHE0uFDhw7NVtnbYostsrlGDz30UK22rUOHDtmiDq+//nqVhR+qE6Et5jHF3KtYWQ+Axk1oAqCk/P73v8+umxTXYLrwwguz+UtLLLFEdh2mY445Jvs6xEVwl1122XT//fen66+/Pls576CDDspWwSv2CsWiDJ9++mm2GMPdd9+dhasIWvvtt1+Ntyt+d1xv6cgjj0x//etfZ/v42N4xY8ZkS6ID0Lg1K9T0YhYAQK54a42V/GKO1umnn65aAI2cniYAqCM//vhjGjJkSHrnnXfSZ599lg488EC1BWgChCYAqCOxbHkMA5wxY0Y2tHDppZdWW4AmwPA8AACAHJYcBwAAyCE0AQAA5BCaAAAAcghNAAAAOYQmAACAHEITAABADqEJAAAgh9AEAACQQ2gCAABIs/b/AF1tvKUDoPojAAAAAElFTkSuQmCC",
-      "text/plain": [
-       "<Figure size 1000x600 with 1 Axes>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
-   "source": [
-    "# Plot bar chart\n",
-    "plt.figure(figsize=(10, 6))\n",
-    "sns.barplot(data=country_counts, x=\"Country\", y=\"RecordCount\", palette=\"viridis\")\n",
-    "plt.title(\"Record Count by Country\")\n",
-    "plt.xticks(rotation=45)\n",
-    "plt.show()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "887b2525",
-   "metadata": {},
-   "source": [
-    "## Pivot Table Example"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 8,
-   "id": "1e26e06b",
-   "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>Age</th>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country</th>\n",
-       "      <th></th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>Country_0</th>\n",
-       "      <td>43.7</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_1</th>\n",
-       "      <td>43.8</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_2</th>\n",
-       "      <td>51.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_3</th>\n",
-       "      <td>38.2</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_4</th>\n",
-       "      <td>44.3</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_5</th>\n",
-       "      <td>48.3</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_6</th>\n",
-       "      <td>47.3</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_7</th>\n",
-       "      <td>41.1</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_8</th>\n",
-       "      <td>40.5</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>Country_9</th>\n",
-       "      <td>47.1</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "            Age\n",
-       "Country        \n",
-       "Country_0  43.7\n",
-       "Country_1  43.8\n",
-       "Country_2  51.0\n",
-       "Country_3  38.2\n",
-       "Country_4  44.3\n",
-       "Country_5  48.3\n",
-       "Country_6  47.3\n",
-       "Country_7  41.1\n",
-       "Country_8  40.5\n",
-       "Country_9  47.1"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
-   "source": [
-    "# If 'Age' exists, average age by country (example only if dataset has relevant column)\n",
-    "if \"Age\" in df.columns:\n",
-    "    age_pivot = df.pivot_table(index=\"Country\", values=\"Age\", aggfunc=\"mean\")\n",
-    "    display(age_pivot)\n",
-    "else:\n",
-    "    print(\"No 'Age' column in dataset to pivot on.\")"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "d9793c4e",
-   "metadata": {},
-   "source": [
-    "\n",
-    "## Summary\n",
-    "\n",
-    "In this notebook, we:\n",
-    "- Loaded a sample CSV dataset\n",
-    "- Explored its structure\n",
-    "- Grouped and counted records by country\n",
-    "- Visualized results with a bar chart\n",
-    "- Created a pivot table (if applicable)\n",
-    "\n",
-    "Try modifying this notebook for your own datasets or audit use cases!\n",
-    "    "
-   ]
-  }
- ],
- "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.14.2"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/notebooks/.ipynb_checkpoints/racf_access_analysis-checkpoint.ipynb b/notebooks/.ipynb_checkpoints/racf_access_analysis-checkpoint.ipynb
deleted file mode 100644
index 3770d66..0000000
--- a/notebooks/.ipynb_checkpoints/racf_access_analysis-checkpoint.ipynb
+++ /dev/null
@@ -1,526 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "markdown",
-   "id": "4c3a8609",
-   "metadata": {},
-   "source": [
-    "\n",
-    "# RACF Access Report Analysis\n",
-    "\n",
-    "This notebook demonstrates how to parse a RACF-like mainframe access report stored in a fixed-width text format, extract user access details, identify unusual access configurations, and summarize the results for follow-up.\n",
-    "\n",
-    "We'll be working with the file `sample_racf_data.txt`.\n",
-    "    "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "a0b3e2b2",
-   "metadata": {},
-   "source": [
-    "\n",
-    "## Install Dependencies\n",
-    "\n",
-    "If you haven't already installed `pandas`, run:\n",
-    "\n",
-    "```bash\n",
-    "pip install pandas\n",
-    "```\n",
-    "    "
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "id": "ca527b49",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import pandas as pd\n",
-    "import re"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "d1694149",
-   "metadata": {},
-   "source": [
-    "## Load RACF Report"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "id": "4891d98b",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "LISTGRP *\n",
-      "INFORMATION FOR GROUP PAYROLLB\n",
-      "SUPERIOR GROUP=RESEARCH     OWNER=IBMUSER   CREATED=06.123\n",
-      "NO INSTALLATION DATA\n",
-      "NO MODEL DATA SET\n",
-      "TERMUACC\n",
-      "NO SUBGROUPS\n",
-      "USER(S)=      ACCESS=      ACCESS COUNT=      UNIVERSAL ACCESS=\n",
-      "IBMUSER       JOIN          000000               ALTER\n",
-      "CONNECT ATTRIBUTES=NONE\n",
-      "REVOKE DATE=NONE                  RESUME DATE=NONE\n",
-      "DAF0          CREATE        000000               READ\n",
-      "CONNECT ATTRIBUTES=NONE\n",
-      "REVOKE DATE=NONE                  RESUME DATE=NONE\n",
-      "IA0           CREATE        000000               READ\n",
-      "CONNECT ATTRIBUTES=ADSP SPECIAL OPERATIONS\n",
-      "REVOKE DATE=NONE                  RESUME DATE=NONE\n",
-      "AEH0          CREATE        000000               READ\n",
-      "CONNECT ATTRIBUTES=NONE\n",
-      "REVOKE DATE=NONE                  RESUME DATE=NONE\n"
-     ]
-    }
-   ],
-   "source": [
-    "with open(\"sample_racf_data.txt\", \"r\") as file:\n",
-    "    lines = file.readlines()\n",
-    "\n",
-    "# Preview first 20 lines\n",
-    "for line in lines[:20]:\n",
-    "    print(line.strip())"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "9d5ee64a",
-   "metadata": {},
-   "source": [
-    "## Parse User Access Records"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "id": "18f06bc9",
-   "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>Group</th>\n",
-       "      <th>User</th>\n",
-       "      <th>Access</th>\n",
-       "      <th>Access Count</th>\n",
-       "      <th>Universal Access</th>\n",
-       "      <th>Attributes</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>IBMUSER</td>\n",
-       "      <td>JOIN</td>\n",
-       "      <td>0</td>\n",
-       "      <td>ALTER</td>\n",
-       "      <td>NONE</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>DAF0</td>\n",
-       "      <td>CREATE</td>\n",
-       "      <td>0</td>\n",
-       "      <td>READ</td>\n",
-       "      <td>NONE</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>IA0</td>\n",
-       "      <td>CREATE</td>\n",
-       "      <td>0</td>\n",
-       "      <td>READ</td>\n",
-       "      <td>ADSP SPECIAL OPERATIONS</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>AEH0</td>\n",
-       "      <td>CREATE</td>\n",
-       "      <td>0</td>\n",
-       "      <td>READ</td>\n",
-       "      <td>NONE</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>RESEARCH</td>\n",
-       "      <td>IBMUSER</td>\n",
-       "      <td>JOIN</td>\n",
-       "      <td>0</td>\n",
-       "      <td>ALTER</td>\n",
-       "      <td>NONE</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "      Group     User  Access  Access Count Universal Access  \\\n",
-       "0  PAYROLLB  IBMUSER    JOIN             0            ALTER   \n",
-       "1  PAYROLLB     DAF0  CREATE             0             READ   \n",
-       "2  PAYROLLB      IA0  CREATE             0             READ   \n",
-       "3  PAYROLLB     AEH0  CREATE             0             READ   \n",
-       "4  RESEARCH  IBMUSER    JOIN             0            ALTER   \n",
-       "\n",
-       "                Attributes  \n",
-       "0                     NONE  \n",
-       "1                     NONE  \n",
-       "2  ADSP SPECIAL OPERATIONS  \n",
-       "3                     NONE  \n",
-       "4                     NONE  "
-      ]
-     },
-     "execution_count": 3,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "# Initialize lists to hold parsed records\n",
-    "records = []\n",
-    "current_group = \"\"\n",
-    "\n",
-    "for i, line in enumerate(lines):\n",
-    "    if \"INFORMATION FOR GROUP\" in line:\n",
-    "        current_group = line.strip().split()[-1]\n",
-    "\n",
-    "    # Identify user lines: starts with a non-empty, non-space string followed by access keywords\n",
-    "    match = re.match(r\"^\\s*(\\S+)\\s+(JOIN|CREATE|CONNECT|USE)\\s+(\\d{6})\\s+(\\S+)\", line)\n",
-    "    if match:\n",
-    "        user, access, access_count, universal_access = match.groups()\n",
-    "\n",
-    "        # Look ahead for CONNECT ATTRIBUTES line\n",
-    "        attr_line = lines[i + 1].strip() if (i + 1) < len(lines) else \"\"\n",
-    "        attr_match = re.search(r\"CONNECT ATTRIBUTES=(.*)\", attr_line)\n",
-    "        attributes = attr_match.group(1) if attr_match else \"NONE\"\n",
-    "\n",
-    "        records.append(\n",
-    "            {\n",
-    "                \"Group\": current_group,\n",
-    "                \"User\": user,\n",
-    "                \"Access\": access,\n",
-    "                \"Access Count\": int(access_count),\n",
-    "                \"Universal Access\": universal_access,\n",
-    "                \"Attributes\": attributes,\n",
-    "            }\n",
-    "        )\n",
-    "\n",
-    "# Convert to DataFrame\n",
-    "df = pd.DataFrame(records)\n",
-    "df.head()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "ab5546a6",
-   "metadata": {},
-   "source": [
-    "## Analyze Access Data"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "id": "d1b8269a",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Access\n",
-      "CREATE     5\n",
-      "JOIN       4\n",
-      "USE        3\n",
-      "CONNECT    1\n",
-      "Name: count, dtype: int64\n"
-     ]
-    },
-    {
-     "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>Group</th>\n",
-       "      <th>User</th>\n",
-       "      <th>Access</th>\n",
-       "      <th>Access Count</th>\n",
-       "      <th>Universal Access</th>\n",
-       "      <th>Attributes</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>IBMUSER</td>\n",
-       "      <td>JOIN</td>\n",
-       "      <td>0</td>\n",
-       "      <td>ALTER</td>\n",
-       "      <td>NONE</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>IA0</td>\n",
-       "      <td>CREATE</td>\n",
-       "      <td>0</td>\n",
-       "      <td>READ</td>\n",
-       "      <td>ADSP SPECIAL OPERATIONS</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>RESEARCH</td>\n",
-       "      <td>IBMUSER</td>\n",
-       "      <td>JOIN</td>\n",
-       "      <td>0</td>\n",
-       "      <td>ALTER</td>\n",
-       "      <td>NONE</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>6</th>\n",
-       "      <td>RESEARCH</td>\n",
-       "      <td>IA0</td>\n",
-       "      <td>CONNECT</td>\n",
-       "      <td>4</td>\n",
-       "      <td>READ</td>\n",
-       "      <td>ADSP SPECIAL OPERATIONS</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "      Group     User   Access  Access Count Universal Access  \\\n",
-       "0  PAYROLLB  IBMUSER     JOIN             0            ALTER   \n",
-       "2  PAYROLLB      IA0   CREATE             0             READ   \n",
-       "4  RESEARCH  IBMUSER     JOIN             0            ALTER   \n",
-       "6  RESEARCH      IA0  CONNECT             4             READ   \n",
-       "\n",
-       "                Attributes  \n",
-       "0                     NONE  \n",
-       "2  ADSP SPECIAL OPERATIONS  \n",
-       "4                     NONE  \n",
-       "6  ADSP SPECIAL OPERATIONS  "
-      ]
-     },
-     "execution_count": 4,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "# Count users by Access type\n",
-    "access_summary = df[\"Access\"].value_counts()\n",
-    "print(access_summary)\n",
-    "\n",
-    "# Identify users with ALTER access or SPECIAL OPERATIONS attribute\n",
-    "anomalies = df[\n",
-    "    (df[\"Universal Access\"] == \"ALTER\")\n",
-    "    | (df[\"Attributes\"].str.contains(\"SPECIAL OPERATIONS\"))\n",
-    "]\n",
-    "\n",
-    "anomalies"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "38201382",
-   "metadata": {},
-   "source": [
-    "## Prepare Follow-Up Report"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 5,
-   "id": "a885710c",
-   "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>Group</th>\n",
-       "      <th>User</th>\n",
-       "      <th>Access</th>\n",
-       "      <th>Universal Access</th>\n",
-       "      <th>Attributes</th>\n",
-       "      <th>Notes</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>IBMUSER</td>\n",
-       "      <td>JOIN</td>\n",
-       "      <td>ALTER</td>\n",
-       "      <td>NONE</td>\n",
-       "      <td>Review access appropriateness with system owner</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>PAYROLLB</td>\n",
-       "      <td>IA0</td>\n",
-       "      <td>CREATE</td>\n",
-       "      <td>READ</td>\n",
-       "      <td>ADSP SPECIAL OPERATIONS</td>\n",
-       "      <td>Review access appropriateness with system owner</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>RESEARCH</td>\n",
-       "      <td>IBMUSER</td>\n",
-       "      <td>JOIN</td>\n",
-       "      <td>ALTER</td>\n",
-       "      <td>NONE</td>\n",
-       "      <td>Review access appropriateness with system owner</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>RESEARCH</td>\n",
-       "      <td>IA0</td>\n",
-       "      <td>CONNECT</td>\n",
-       "      <td>READ</td>\n",
-       "      <td>ADSP SPECIAL OPERATIONS</td>\n",
-       "      <td>Review access appropriateness with system owner</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "      Group     User   Access Universal Access               Attributes  \\\n",
-       "0  PAYROLLB  IBMUSER     JOIN            ALTER                     NONE   \n",
-       "1  PAYROLLB      IA0   CREATE             READ  ADSP SPECIAL OPERATIONS   \n",
-       "2  RESEARCH  IBMUSER     JOIN            ALTER                     NONE   \n",
-       "3  RESEARCH      IA0  CONNECT             READ  ADSP SPECIAL OPERATIONS   \n",
-       "\n",
-       "                                             Notes  \n",
-       "0  Review access appropriateness with system owner  \n",
-       "1  Review access appropriateness with system owner  \n",
-       "2  Review access appropriateness with system owner  \n",
-       "3  Review access appropriateness with system owner  "
-      ]
-     },
-     "execution_count": 5,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "# Create a concise follow-up report\n",
-    "follow_up = anomalies[\n",
-    "    [\"Group\", \"User\", \"Access\", \"Universal Access\", \"Attributes\"]\n",
-    "].copy()\n",
-    "follow_up[\"Notes\"] = \"Review access appropriateness with system owner\"\n",
-    "\n",
-    "follow_up.reset_index(drop=True, inplace=True)\n",
-    "follow_up"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "0158f787",
-   "metadata": {},
-   "source": [
-    "\n",
-    "## Summary\n",
-    "\n",
-    "In this notebook, we:\n",
-    "- Parsed a RACF-like access report from a fixed-width text file\n",
-    "- Extracted key fields into a structured DataFrame\n",
-    "- Analyzed access configurations for high-risk permissions\n",
-    "- Summarized anomalies requiring follow-up with system owners\n",
-    "\n",
-    "Use this as a starting point for mainframe audit automation projects!\n",
-    "    "
-   ]
-  }
- ],
- "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.14.2"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}