# Buggy code
def pandas(tclass, *targs, **tkwargs):
    """
    Registers the given `tqdm` class with
        pandas.core.
        ( frame.DataFrame
        | series.Series
        | groupby.DataFrameGroupBy
        | groupby.SeriesGroupBy
        ).progress_apply

    A new instance will be create every time `progress_apply` is called,
    and each instance will automatically close() upon completion.

    Parameters
    ----------
    targs, tkwargs  : arguments for the tqdm instance

    Examples
    --------
    >>> import pandas as pd
    >>> import numpy as np
    >>> from tqdm import tqdm, tqdm_gui
    >>>
    >>> df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
    >>> tqdm.pandas(ncols=50)  # can use tqdm_gui, optional kwargs, etc
    >>> # Now you can use `progress_apply` instead of `apply`
    >>> df.groupby(0).progress_apply(lambda x: x**2)

    References
    ----------
    https://stackoverflow.com/questions/18603270/
    progress-indicator-during-pandas-operations-python
    """
    from pandas.core.frame import DataFrame
    from pandas.core.series import Series
    from pandas import Panel

    try:
        # pandas>=0.18.0
        from pandas.core.window import _Rolling_and_Expanding
    except ImportError:  # pragma: no cover
        _Rolling_and_Expanding = None
    try:
        # pandas>=0.23.0
        from pandas.core.groupby.groupby import DataFrameGroupBy
        from pandas.core.groupby.groupby import SeriesGroupBy
        from pandas.core.groupby.groupby import GroupBy
        from pandas.core.groupby.groupby import PanelGroupBy
    except ImportError:
        from pandas.core.groupby import DataFrameGroupBy
        from pandas.core.groupby import SeriesGroupBy
        from pandas.core.groupby import GroupBy
        from pandas.core.groupby import PanelGroupBy

    deprecated_t = [tkwargs.pop("deprecated_t", None)]

    def inner_generator(df_function="apply"):
        def inner(df, func, *args, **kwargs):
            """
            Parameters
            ----------
            df  : (DataFrame|Series)[GroupBy]
                Data (may be grouped).
            func  : function
                To be applied on the (grouped) data.
            **kwargs  : optional
                Transmitted to `df.apply()`.
            """

            # Precompute total iterations
            total = tkwargs.pop("total", getattr(df, "ngroups", None))
            if total is None:  # not grouped
                if df_function == "applymap":
                    total = df.size
                elif isinstance(df, Series):
                    total = len(df)
                elif _Rolling_and_Expanding is None or not isinstance(
                    df, _Rolling_and_Expanding
                ):
                    # DataFrame or Panel
                    axis = kwargs.get("axis", 0)
                    # when axis=0, total is shape[axis1]
                    total = df.size // df.shape[axis]

            # Init bar
            if deprecated_t[0] is not None:
                t = deprecated_t[0]
                deprecated_t[0] = None
            else:
                t = tclass(*targs, total=total, **tkwargs)

            if len(args) > 0:
                # *args intentionally not supported (see #244, #299)
                TqdmDeprecationWarning(
                    "Except func, normal arguments are intentionally"
                    + " not supported by"
                    + " `(DataFrame|Series|GroupBy).progress_apply`."
                    + " Use keyword arguments instead.",
                    fp_write=getattr(t.fp, "write", sys.stderr.write),
                )

            # Define bar updating wrapper
            def wrapper(*args, **kwargs):
                # update tbar correctly
                # it seems `pandas apply` calls `func` twice
                # on the first column/row to decide whether it can
                # take a fast or slow code path; so stop when t.total==t.n
                t.update(n=1 if not t.total or t.n < t.total else 0)
                return func(*args, **kwargs)

            # Apply the provided function (in **kwargs)
            # on the df using our wrapper (which provides bar updating)
            result = getattr(df, df_function)(wrapper, **kwargs)

            # Close bar and return pandas calculation result
            t.close()
            return result

        return inner

    # Monkeypatch pandas to provide easy methods
    # Enable custom tqdm progress in pandas!
    Series.progress_apply = inner_generator()
    SeriesGroupBy.progress_apply = inner_generator()
    Series.progress_map = inner_generator("map")
    SeriesGroupBy.progress_map = inner_generator("map")

    DataFrame.progress_apply = inner_generator()
    DataFrameGroupBy.progress_apply = inner_generator()
    DataFrame.progress_applymap = inner_generator("applymap")

    Panel.progress_apply = inner_generator()
    PanelGroupBy.progress_apply = inner_generator()

    GroupBy.progress_apply = inner_generator()
    GroupBy.progress_aggregate = inner_generator("aggregate")
    GroupBy.progress_transform = inner_generator("transform")

    if _Rolling_and_Expanding is not None:  # pragma: no cover
        _Rolling_and_Expanding.progress_apply = inner_generator()


# Traceback (ImportError)
from tqdm import tqdm
tqdm.pandas()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/username/.conda/envs/py36/lib/python3.6/site-packages/tqdm/_tqdm.py", line 545, in pandas
from pandas.core.groupby import PanelGroupBy
ImportError: cannot import name 'PanelGroupBy'

# Fixed code
def pandas(tclass, *targs, **tkwargs):
    """
    Registers the given `tqdm` class with
        pandas.core.
        ( frame.DataFrame
        | series.Series
        | groupby.DataFrameGroupBy
        | groupby.SeriesGroupBy
        ).progress_apply

    A new instance will be create every time `progress_apply` is called,
    and each instance will automatically close() upon completion.

    Parameters
    ----------
    targs, tkwargs  : arguments for the tqdm instance

    Examples
    --------
    >>> import pandas as pd
    >>> import numpy as np
    >>> from tqdm import tqdm, tqdm_gui
    >>>
    >>> df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
    >>> tqdm.pandas(ncols=50)  # can use tqdm_gui, optional kwargs, etc
    >>> # Now you can use `progress_apply` instead of `apply`
    >>> df.groupby(0).progress_apply(lambda x: x**2)

    References
    ----------
    https://stackoverflow.com/questions/18603270/
    progress-indicator-during-pandas-operations-python
    """
    from pandas.core.frame import DataFrame
    from pandas.core.series import Series
    from pandas import Panel

    try:
        # pandas>=0.18.0
        from pandas.core.window import _Rolling_and_Expanding
    except ImportError:  # pragma: no cover
        _Rolling_and_Expanding = None
    try:
        # pandas>=0.23.0
        from pandas.core.groupby.groupby import (
            DataFrameGroupBy,
            SeriesGroupBy,
            GroupBy,
            PanelGroupBy,
        )
    except ImportError:
        from pandas.core.groupby import (
            DataFrameGroupBy,
            SeriesGroupBy,
            GroupBy,
            PanelGroupBy,
        )

    deprecated_t = [tkwargs.pop("deprecated_t", None)]

    def inner_generator(df_function="apply"):
        def inner(df, func, *args, **kwargs):
            """
            Parameters
            ----------
            df  : (DataFrame|Series)[GroupBy]
                Data (may be grouped).
            func  : function
                To be applied on the (grouped) data.
            **kwargs  : optional
                Transmitted to `df.apply()`.
            """

            # Precompute total iterations
            total = tkwargs.pop("total", getattr(df, "ngroups", None))
            if total is None:  # not grouped
                if df_function == "applymap":
                    total = df.size
                elif isinstance(df, Series):
                    total = len(df)
                elif _Rolling_and_Expanding is None or not isinstance(
                    df, _Rolling_and_Expanding
                ):
                    # DataFrame or Panel
                    axis = kwargs.get("axis", 0)
                    # when axis=0, total is shape[axis1]
                    total = df.size // df.shape[axis]

            # Init bar
            if deprecated_t[0] is not None:
                t = deprecated_t[0]
                deprecated_t[0] = None
            else:
                t = tclass(*targs, total=total, **tkwargs)

            if len(args) > 0:
                # *args intentionally not supported (see #244, #299)
                TqdmDeprecationWarning(
                    "Except func, normal arguments are intentionally"
                    + " not supported by"
                    + " `(DataFrame|Series|GroupBy).progress_apply`."
                    + " Use keyword arguments instead.",
                    fp_write=getattr(t.fp, "write", sys.stderr.write),
                )

            # Define bar updating wrapper
            def wrapper(*args, **kwargs):
                # update tbar correctly
                # it seems `pandas apply` calls `func` twice
                # on the first column/row to decide whether it can
                # take a fast or slow code path; so stop when t.total==t.n
                t.update(n=1 if not t.total or t.n < t.total else 0)
                return func(*args, **kwargs)

            # Apply the provided function (in **kwargs)
            # on the df using our wrapper (which provides bar updating)
            result = getattr(df, df_function)(wrapper, **kwargs)

            # Close bar and return pandas calculation result
            t.close()
            return result

        return inner

    # Monkeypatch pandas to provide easy methods
    # Enable custom tqdm progress in pandas!
    Series.progress_apply = inner_generator()
    SeriesGroupBy.progress_apply = inner_generator()
    Series.progress_map = inner_generator("map")
    SeriesGroupBy.progress_map = inner_generator("map")

    DataFrame.progress_apply = inner_generator()
    DataFrameGroupBy.progress_apply = inner_generator()
    DataFrame.progress_applymap = inner_generator("applymap")

    Panel.progress_apply = inner_generator()
    PanelGroupBy.progress_apply = inner_generator()

    GroupBy.progress_apply = inner_generator()
    GroupBy.progress_aggregate = inner_generator("aggregate")
    GroupBy.progress_transform = inner_generator("transform")

    if _Rolling_and_Expanding is not None:  # pragma: no cover
        _Rolling_and_Expanding.progress_apply = inner_generator()