Fits the JointPlot, creating a correlative visualization between the columns
        specified during initialization and the data and target passed into fit:

            - If self.columns is None then X and y must both be specified as 1D arrays
              or X must be a 2D array with only 2 columns.
            - If self.columns is a single int or str, that column is selected to be
              visualized against the target y.
            - If self.columns is two ints or strs, those columns are visualized against
              each other. If y is specified then it is used to color the points.

        This is the main entry point into the joint plot visualization.

        Parameters
        ----------
        X : array-like
            An array-like object of either 1 or 2 dimensions depending on self.columns.
            Usually this is a 2D table with shape (n, m)

        y : array-like, default: None
            An vector or 1D array that has the same length as X. May be used to either
            directly plot data or to color data points.

def fit(self, X, y=None):
        """
        Fits the JointPlot, creating a correlative visualization between the columns
        specified during initialization and the data and target passed into fit:

            - If self.columns is None then X and y must both be specified as 1D arrays
              or X must be a 2D array with only 2 columns.
            - If self.columns is a single int or str, that column is selected to be
              visualized against the target y.
            - If self.columns is two ints or strs, those columns are visualized against
              each other. If y is specified then it is used to color the points.

        This is the main entry point into the joint plot visualization.

        Parameters
        ----------
        X : array-like
            An array-like object of either 1 or 2 dimensions depending on self.columns.
            Usually this is a 2D table with shape (n, m)

        y : array-like, default: None
            An vector or 1D array that has the same length as X. May be used to either
            directly plot data or to color data points.
        """
        # Convert python objects to numpy arrays
        if isinstance(X, (list, tuple)):
            X = np.array(X)

        if y is not None and isinstance(y, (list, tuple)):
            y = np.array(y)

        # Case where no columns are specified
        if self.columns is None:
            if (y is None and (X.ndim != 2 or X.shape[1] != 2)) or (y is not None and (X.ndim != 1 or y.ndim != 1)):
                raise YellowbrickValueError((
                    "when self.columns is None specify either X and y as 1D arrays "
                    "or X as a matrix with 2 columns"
                ))

            if y is None:
                # Draw the first column as x and the second column as y
                self.draw(X[:,0], X[:,1], xlabel="0", ylabel="1")
                return self

            # Draw x against y
            self.draw(X, y, xlabel="x", ylabel="y")
            return self

        # Case where a single string or int index is specified
        if isinstance(self.columns, (int,str)):
            if y is None:
                raise YellowbrickValueError(
                    "when self.columns is a single index, y must be specified"
                )

            # fetch the index from X -- raising index error if not possible
            x = self._index_into(self.columns, X)
            self.draw(x, y, xlabel=str(self.columns), ylabel="target")
            return self

        # Case where there is a double index for both columns
        columns = tuple(self.columns)
        if len(columns) != 2:
            raise YellowbrickValueError((
                    "'{}' contains too many indices or is invalid for joint plot"
                ).format(columns))

        # TODO: color the points based on the target if it is given
        x = self._index_into(columns[0], X)
        y = self._index_into(columns[1], X)
        self.draw(x, y, xlabel=str(columns[0]), ylabel=str(columns[1]))
        return self