<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 seaborn.jointplot
Seaborn's jointplot displays a relationship between 2 variables (bivariate) as well as 1D profiles (univariate) in the margins. This plot is a convenience class that wraps JointGrid.
Step1:  The multivariate normal distribution is a nice tool to demonstrate this type of plot as it is sampling from a multidimensional Gaussian and there is natural clustering. I'll set the covariance matrix equal to the identity so that the X and Y variables are uncorrelated -- meaning we will just get a blob
Step2:  Default plot
Step3:  Currently, jointplot wraps JointGrid with the following options for kind
Step4:  'reg' plots a linear regression line. Here the line is close to flat because we chose our variables to be uncorrelated
Step5:  'resid' plots the residual of the data to the regression line -- which is not very useful for this specific example because our regression line is almost flat and thus the residual is almost the same as the data.
Step6:  kde plots a kernel density estimate in the margins and converts the interior into a shaded countour plot
Step7:  'hex' bins the data into hexagons with histograms in the margins. At this point you probably see the "pre-cooked" nature of jointplot. It provides nice defaults, but if you wanted, for example, a KDE on the margin of this hexplot you will need to use JointGrid.
Step8:  stat_func can be used to provide a function for computing a summary statistic from the data. The full x, y data vectors are passed in, so the function must provide one value or a tuple from many. As an example, I'll provide tmin, which when used in this way will return the smallest value of x that was greater than its corresponding value of y.
Step9:  Change the color
Step10:  Create separation between 2D plot and marginal plots with space
Step11:  xlim and ylim can be used to adjust the field of view
Step12:  Pass additional parameters to the marginal plots with marginal_kws. You can pass similar options to joint_kws and annot_kws
Step13:  Finalize
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
plt.rcParams['figure.figsize'] = (20.0, 10.0)
plt.rcParams['font.family'] = "serif"
Explanation: seaborn.jointplot
Seaborn's jointplot displays a relationship between 2 variables (bivariate) as well as 1D profiles (univariate) in the margins. This plot is a convenience class that wraps JointGrid.
End of explanation
# Generate some random multivariate data
x, y = np.random.RandomState(8).multivariate_normal([0, 0], [(1, 0), (0, 1)], 1000).T
df = pd.DataFrame({"x":x,"y":y})
Explanation: The multivariate normal distribution is a nice tool to demonstrate this type of plot as it is sampling from a multidimensional Gaussian and there is natural clustering. I'll set the covariance matrix equal to the identity so that the X and Y variables are uncorrelated -- meaning we will just get a blob
End of explanation
p = sns.jointplot(data=df,x='x', y='y')
Explanation: Default plot
End of explanation
p = sns.jointplot(data=df,x='x', y='y',kind='scatter')
Explanation: Currently, jointplot wraps JointGrid with the following options for kind:
    - scatter
    - reg
    - resid 
    - kde 
    - hex 
Scatter is the default parameters
End of explanation
p = sns.jointplot(data=df,x='x', y='y',kind='reg')
Explanation: 'reg' plots a linear regression line. Here the line is close to flat because we chose our variables to be uncorrelated
End of explanation
x2, y2 = np.random.RandomState(9).multivariate_normal([0, 0], [(1, 0), (0, 1)], len(x)).T
df2 = pd.DataFrame({"x":x,"y":y2})
p = sns.jointplot(data=df,x='x', y='y',kind='resid')
Explanation: 'resid' plots the residual of the data to the regression line -- which is not very useful for this specific example because our regression line is almost flat and thus the residual is almost the same as the data.
End of explanation
p = sns.jointplot(data=df,x='x', y='y',kind='kde')
Explanation: kde plots a kernel density estimate in the margins and converts the interior into a shaded countour plot
End of explanation
p = sns.jointplot(data=df,x='x', y='y',kind='hex')
Explanation: 'hex' bins the data into hexagons with histograms in the margins. At this point you probably see the "pre-cooked" nature of jointplot. It provides nice defaults, but if you wanted, for example, a KDE on the margin of this hexplot you will need to use JointGrid.
End of explanation
from scipy.stats import tmin
p = sns.jointplot(data=df, x='x', y='y',kind='kde',stat_func=tmin)
# tmin is computing roughly the equivalent of the following
print(df.loc[df.x>df.y,'x'].min())
Explanation: stat_func can be used to provide a function for computing a summary statistic from the data. The full x, y data vectors are passed in, so the function must provide one value or a tuple from many. As an example, I'll provide tmin, which when used in this way will return the smallest value of x that was greater than its corresponding value of y.
End of explanation
p = sns.jointplot(data=df,
                  x='x',
                  y='y',
                  kind='kde',
                  color="#99ffff")
p = sns.jointplot(data=df,
                  x='x',
                  y='y',
                  kind='kde',
                  ratio=1)
Explanation: Change the color
End of explanation
p = sns.jointplot(data=df,
                  x='x',
                  y='y',
                  kind='kde',
                  space=2)
Explanation: Create separation between 2D plot and marginal plots with space
End of explanation
p = sns.jointplot(data=df,
                  x='x',
                  y='y',
                  kind='kde',
                  xlim=(-15,15),
                  ylim=(-15,15))
Explanation: xlim and ylim can be used to adjust the field of view
End of explanation
p = sns.jointplot(data=df,
                  x='x',
                  y='y',
                  kind='kde',
                  marginal_kws={'lw':5,
                                'color':'red'})
Explanation: Pass additional parameters to the marginal plots with marginal_kws. You can pass similar options to joint_kws and annot_kws
End of explanation
from itertools import chain
p = sns.jointplot(data=df,
                  x='x',
                  y='y',
                  kind='kde',
                  xlim=(-3,3),
                  ylim=(-3,3),
                  marginal_kws={'lw':3}).set_axis_labels('X','Y')
p.ax_marg_x.set_facecolor('#ccffcc')
p.ax_marg_y.set_facecolor('#ccffcc')
for l in chain(p.ax_marg_x.axes.lines,p.ax_marg_y.axes.lines):
    l.set_linestyle('--')
    l.set_color('black')
[d for d in dir(p.ax_marg_x.axes) if "line" in d]
for l in p.ax_marg_x.axes.lines:
    print(dir(l))
Explanation: Finalize
End of explanation
<END_TASK>