First fit a transformer using the SFrame `data` and then return a transformed
        version of `data`.

        Parameters
        ----------
        data : SFrame
            The data used to fit the transformer. The same data is then also
            transformed.

        Returns
        -------
        Transformed SFrame.

        See Also
        --------
        transform, fit_transform

        Notes
        -----
        - The default implementation calls fit() and then calls transform().
          You may override this function with a more efficient implementation."

        Examples
        --------
        .. sourcecode:: python

          >> transformed_sf = chain.fit_transform(sf)

def fit_transform(self, data):
        """
        First fit a transformer using the SFrame `data` and then return a transformed
        version of `data`.

        Parameters
        ----------
        data : SFrame
            The data used to fit the transformer. The same data is then also
            transformed.

        Returns
        -------
        Transformed SFrame.

        See Also
        --------
        transform, fit_transform

        Notes
        -----
        - The default implementation calls fit() and then calls transform().
          You may override this function with a more efficient implementation."

        Examples
        --------
        .. sourcecode:: python

          >> transformed_sf = chain.fit_transform(sf)

        """
        if not self._transformers:
            return self._preprocess(data)

        transformed_data = self._preprocess(data)
        final_step = self._transformers[-1]
        return final_step[1].fit_transform(transformed_data)