{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "hide"
    ]
   },
   "outputs": [],
   "source": [
    "import seaborn as sns; sns.set_theme()\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "Calling the constructor sets up a blank grid of subplots with each row and one column corresponding to a numeric variable in the dataset:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "penguins = sns.load_dataset(\"penguins\")\n",
    "g = sns.PairGrid(penguins)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "Passing a bivariate function to :meth:`PairGrid.map` will draw a bivariate plot on every axes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins)\n",
    "g.map(sns.scatterplot)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "Passing separate functions to :meth:`PairGrid.map_diag` and :meth:`PairGrid.map_offdiag` will show each variable's marginal distribution on the diagonal:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins)\n",
    "g.map_diag(sns.histplot)\n",
    "g.map_offdiag(sns.scatterplot)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "It's also possible to use different functions on the upper and lower triangles of the plot (which are otherwise redundant):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins, diag_sharey=False)\n",
    "g.map_upper(sns.scatterplot)\n",
    "g.map_lower(sns.kdeplot)\n",
    "g.map_diag(sns.kdeplot)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "Or to avoid the redundancy altogether:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins, diag_sharey=False, corner=True)\n",
    "g.map_lower(sns.scatterplot)\n",
    "g.map_diag(sns.kdeplot)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "The :class:`PairGrid` constructor accepts a ``hue`` variable. This variable is passed directly to functions that understand it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins, hue=\"species\")\n",
    "g.map_diag(sns.histplot)\n",
    "g.map_offdiag(sns.scatterplot)\n",
    "g.add_legend()"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "But you can also pass matplotlib functions, in which case a groupby is performed internally and a separate plot is drawn for each level:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins, hue=\"species\")\n",
    "g.map_diag(plt.hist)\n",
    "g.map_offdiag(plt.scatter)\n",
    "g.add_legend()"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "Additional semantic variables can be assigned by passing data vectors directly while mapping the function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins, hue=\"species\")\n",
    "g.map_diag(sns.histplot)\n",
    "g.map_offdiag(sns.scatterplot, size=penguins[\"sex\"])\n",
    "g.add_legend(title=\"\", adjust_subtitles=True)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "When using seaborn functions that can implement a numeric hue mapping, you will want to disable mapping of the variable on the diagonal axes. Note that the ``hue`` variable is excluded from the list of variables shown by default:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins, hue=\"body_mass_g\")\n",
    "g.map_diag(sns.histplot, hue=None, color=\".3\")\n",
    "g.map_offdiag(sns.scatterplot)\n",
    "g.add_legend()"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "The ``vars`` parameter can be used to control exactly which variables are used:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "variables = [\"body_mass_g\", \"bill_length_mm\", \"flipper_length_mm\"]\n",
    "g = sns.PairGrid(penguins, hue=\"body_mass_g\", vars=variables)\n",
    "g.map_diag(sns.histplot, hue=None, color=\".3\")\n",
    "g.map_offdiag(sns.scatterplot)\n",
    "g.add_legend()"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "The plot need not be square: separate variables can be used to define the rows and columns:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_vars = [\"body_mass_g\", \"bill_length_mm\", \"bill_depth_mm\", \"flipper_length_mm\"]\n",
    "y_vars = [\"body_mass_g\"]\n",
    "g = sns.PairGrid(penguins, hue=\"species\", x_vars=x_vars, y_vars=y_vars)\n",
    "g.map_diag(sns.histplot, color=\".3\")\n",
    "g.map_offdiag(sns.scatterplot)\n",
    "g.add_legend()"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "It can be useful to explore different approaches to resolving multiple distributions on the diagonal axes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = sns.PairGrid(penguins, hue=\"species\")\n",
    "g.map_diag(sns.histplot, multiple=\"stack\", element=\"step\")\n",
    "g.map_offdiag(sns.scatterplot)\n",
    "g.add_legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py310",
   "language": "python",
   "name": "py310"
  },
  "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.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
