code: def qqplot(
      x,
      dist="norm",
      sparams=(),
      confidence=0.95,
      square=True,
      ax=None,
      **kwargs,
  ):
      """Quantile-Quantile plot.
  
      Parameters
      ----------
      x : array_like
          Sample data.
      dist : str or stats.distributions instance, optional
          Distribution or distribution function name. The default is `'norm'`
          for a normal probability plot.
      sparams : tuple, optional
          Distribution-specific shape parameters (shape parameters, location,
          and scale). See :py:func:`scipy.stats.probplot` for more details.
      confidence : float
          Confidence level (.95 = 95%) for point-wise confidence envelope.
          Can be disabled by passing False.
      square: bool
          If True (default), ensure equal aspect ratio between X and Y axes.
      ax : matplotlib axes
          Axis on which to draw the plot
      **kwargs : optional
          Optional argument(s) passed to :py:func:`matplotlib.pyplot.scatter`.
  
      Returns
      -------
      ax : Matplotlib Axes instance
          Returns the Axes object with the plot for further tweaking.
  
      Raises
      ------
      ValueError
          If ``sparams`` does not contain the required parameters for ``dist``.
          (e.g. :py:class:`scipy.stats.t` has a mandatory degrees of
          freedom parameter *df*.)
  
      Notes
      -----
      This function returns a scatter plot of the quantile of the sample data
      ``x`` against the theoretical quantiles of the distribution given in
      ``dist`` (default = *'norm'*).
  
      The points plotted in a Q–Q plot are always non-decreasing when viewed
      from left to right. If the two distributions being compared are identical,
      the Q–Q plot follows the 45° line y = x. If the two distributions agree
      after linearly transforming the values in one of the distributions,
      then the Q–Q plot follows some line, but not necessarily the line y = x.
      If the general trend of the Q–Q plot is flatter than the line y = x,
      the distribution plotted on the horizontal axis is more dispersed than
      the distribution plotted on the vertical axis. Conversely, if the general
      trend of the Q–Q plot is steeper than the line y = x, the distribution
      plotted on the vertical axis is more dispersed than the distribution
      plotted on the horizontal axis. Q–Q plots are often arced, or "S" shaped,
      indicating that one of the distributions is more skewed than the other,
      or that one of the distributions has heavier tails than the other.
  
      In addition, the function also plots a best-fit line (linear regression)
      for the data and annotates the plot with the coefficient of
      determination :math:`R^2`. Note that the intercept and slope of the
      linear regression between the quantiles gives a measure of the relative
      location and relative scale of the samples.
  
      .. warning:: Be extra careful when using fancier distributions with several
          parameters. Always double-check your results with another
          software or package.
  
      References
      ----------
      * https://github.com/cran/car/blob/master/R/qqPlot.R
  
      * Fox, J. (2008), Applied Regression Analysis and Generalized Linear
        Models, 2nd Ed., Sage Publications, Inc.
  
      Examples
      --------
      Q-Q plot using a normal theoretical distribution:
  
      .. plot::
  
          >>> import numpy as np
          >>> import pingouin as pg
          >>> np.random.seed(123)
          >>> x = np.random.normal(size=50)
          >>> ax = pg.qqplot(x, dist='norm')
  
      Two Q-Q plots using two separate axes:
  
      .. plot::
  
          >>> import numpy as np
          >>> import pingouin as pg
          >>> import matplotlib.pyplot as plt
          >>> np.random.seed(123)
          >>> x = np.random.normal(size=50)
          >>> x_exp = np.random.exponential(size=50)
          >>> fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4))
          >>> ax1 = pg.qqplot(x, dist='norm', ax=ax1, confidence=False)
          >>> ax2 = pg.qqplot(x_exp, dist='expon', ax=ax2)
  
      Using custom location / scale parameters as well as another Seaborn style
  
      .. plot::
  
          >>> import numpy as np
          >>> import seaborn as sns
          >>> import pingouin as pg
          >>> import matplotlib.pyplot as plt
          >>> np.random.seed(123)
          >>> x = np.random.normal(size=50)
          >>> mean, std = 0, 0.8
          >>> sns.set_style('darkgrid')
          >>> ax = pg.qqplot(x, dist='norm', sparams=(mean, std))
      """
      # Update default kwargs with specified inputs
      _scatter_kwargs = {"marker": "o", "color": "blue"}
      _scatter_kwargs.update(kwargs)
  
      if isinstance(dist, str):
          dist = getattr(stats, dist)
  
      x = np.asarray(x)
      x = x[~np.isnan(x)]  # NaN are automatically removed
  
      # Check sparams: if single parameter, tuple becomes int
      if not isinstance(sparams, (tuple, list)):
          sparams = (sparams,)
      # For fancier distributions, check that the required parameters are passed
      if len(sparams) < dist.numargs:
          raise ValueError(
              "The following sparams are required for this "
              "distribution: %s. See scipy.stats.%s for details."
              % (dist.shapes, dist.name)
          )
  
      # Extract quantiles and regression
      quantiles = stats.probplot(
          x, sparams=sparams, dist=dist, fit=False
      )
      theor, observed = quantiles[0], quantiles[1]
  
      fit_params = dist.fit(x)
      loc = fit_params[-2]
      scale = fit_params[-1]
      shape = fit_params[:-2] if len(fit_params) > 2 else None
  
      # Observed values to observed quantiles
      if loc != 0 and scale != 1:
          observed = (np.sort(observed) - fit_params[-2]) / fit_params[
              -1
          ]
  
      # Linear regression
      slope, intercept, r, _, _ = stats.linregress(theor, observed)
  
      # Start the plot
      if ax is None:
          ax = plt.gca()
  
      ax.scatter(theor, observed, **_scatter_kwargs)
  
      ax.set_xlabel("Theoretical quantiles")
      ax.set_ylabel("Ordered quantiles")
  
      # Add diagonal line
      end_pts = [ax.get_xlim(), ax.get_ylim()]
      end_pts[0] = min(end_pts[0])
      end_pts[1] = max(end_pts[1])
      ax.plot(end_pts, end_pts, color="slategrey", lw=1.5)
      ax.set_xlim(end_pts)
      ax.set_ylim(end_pts)
  
      # Add regression line and annotate R2
      fit_val = slope * theor + intercept
      ax.plot(theor, fit_val, "r-", lw=2)
      posx = end_pts[0] + 0.60 * (end_pts[1] - end_pts[0])
      posy = end_pts[0] + 0.10 * (end_pts[1] - end_pts[0])
      ax.text(posx, posy, "$R^2=%.3f$" % r**2)
  
      if confidence is not False:
          # Confidence envelope
          n = x.size
          P = _ppoints(n)
          crit = stats.norm.ppf(1 - (1 - confidence) / 2)
          pdf = (
              dist.pdf(theor)
              if shape is None
              else dist.pdf(theor, *shape)
          )
          se = (slope / pdf) * np.sqrt(P * (1 - P) / n)
          upper = fit_val + crit * se
          lower = fit_val - crit * se
          ax.plot(theor, upper, "r--", lw=1.25)
          ax.plot(theor, lower, "r--", lw=1.25)
  
      # Make square
      if square:
          ax.set_aspect("equal")
  
      return ax
  
file_path: pingouin/pingouin/plotting.py
imports: import numpy
  import pandas
  import seaborn
  from scipy import stats
  import matplotlib.pyplot
  import matplotlib.transforms
label_desc: Use image node_id 3 for calling a global function with example usage: qqplot(x, dist, sparams, confidence, square, ax) and returns: ax