# Buggy code
def sample(
    self,
    n: Optional[int] = None,
    frac: Optional[float] = None,
    replace: bool = False,
    weights: Optional[Union[Sequence, Series]] = None,
    random_state=None,
):
    """
    Return a random sample of items from each group.

    You can use `random_state` for reproducibility.

    .. versionadded:: 1.1.0

    Parameters
    ----------
    n : int, optional
        Number of items to return for each group. Cannot be used with
        `frac` and must be no larger than the smallest group unless
        `replace` is True. Default is one if `frac` is None.
    frac : float, optional
        Fraction of items to return. Cannot be used with `n`.
    replace : bool, default False
        Allow or disallow sampling of the same row more than once.
    weights : list-like, optional
        Default None results in equal probability weighting.
        If passed a list-like then values must have the same length as
        the underlying DataFrame or Series object and will be used as
        sampling probabilities after normalization within each group.
        Values must be non-negative with at least one positive element
        within each group.
    random_state : int, array-like, BitGenerator, np.random.RandomState, optional
        If int, array-like, or BitGenerator (NumPy>=1.17), seed for
        random number generator
        If np.random.RandomState, use as numpy RandomState object.

    Returns
    -------
    Series or DataFrame
        A new object of same type as caller containing items randomly
        sampled within each group from the caller object.

    See Also
    --------
    DataFrame.sample: Generate random samples from a DataFrame object.
    numpy.random.choice: Generate a random sample from a given 1-D numpy
        array.

    Examples
    --------
    >>> df = pd.DataFrame(
    ...     {"a": ["red"] * 2 + ["blue"] * 2 + ["black"] * 2, "b": range(6)}
    ... )
    >>> df
           a  b
    0    red  0
    1    red  1
    2   blue  2
    3   blue  3
    4  black  4
    5  black  5

    Select one row at random for each distinct value in column a. The
    `random_state` argument can be used to guarantee reproducibility:

    >>> df.groupby("a").sample(n=1, random_state=1)
           a  b
    4  black  4
    2   blue  2
    1    red  1

    Set `frac` to sample fixed proportions rather than counts:

    >>> df.groupby("a")["b"].sample(frac=0.5, random_state=2)
    5    5
    2    2
    0    0
    Name: b, dtype: int64

    Control sample probabilities within groups by setting weights:

    >>> df.groupby("a").sample(
    ...     n=1,
    ...     weights=[1, 1, 1, 0, 0, 1],
    ...     random_state=1,
    ... )
           a  b
    5  black  5
    2   blue  2
    0    red  0
    """
    from pandas.core.reshape.concat import concat

    if weights is not None:
        weights = Series(weights, index=self._selected_obj.index)
        ws = [weights[idx] for idx in self.indices.values()]
    else:
        ws = [None] * self.ngroups

    if random_state is not None:
        random_state = com.random_state(random_state)

    samples = [
        obj.sample(
            n=n, frac=frac, replace=replace, weights=w, random_state=random_state
        )
        for (_, obj), w in zip(self, ws)
    ]

    return concat(samples, axis=self.axis)


# Traceback (KeyError)
Traceback (most recent call last):
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3417, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-4-1fc31a504740>", line 1, in <module>
df1.groupby('c').sample(1, weights=df1['d'].to_numpy())
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/groupby/groupby.py", line 3024, in sample
ws = [weights[idx] for idx in self.indices.values()]
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/groupby/groupby.py", line 3024, in <listcomp>
ws = [weights[idx] for idx in self.indices.values()]
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/series.py", line 875, in __getitem__
return self._get_with(key)
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/series.py", line 910, in _get_with
return self.loc[key]
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/indexing.py", line 895, in __getitem__
return self._getitem_axis(maybe_callable, axis=axis)
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/indexing.py", line 1113, in _getitem_axis
return self._getitem_iterable(key, axis=axis)
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/indexing.py", line 1053, in _getitem_iterable
keyarr, indexer = self._get_listlike_indexer(key, axis, raise_missing=False)
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/indexing.py", line 1266, in _get_listlike_indexer
self._validate_read_indexer(keyarr, indexer, axis, raise_missing=raise_missing)
File "/Users/wenjun/miniconda3/lib/python3.8/site-packages/pandas/core/indexing.py", line 1308, in _validate_read_indexer
raise KeyError(f"None of [{key}] are in the [{axis_name}]")
KeyError: "None of [Int64Index([6, 7], dtype='int64')] are in the [index]"

# Fixed code
def sample(
    self,
    n: Optional[int] = None,
    frac: Optional[float] = None,
    replace: bool = False,
    weights: Optional[Union[Sequence, Series]] = None,
    random_state=None,
):
    """
    Return a random sample of items from each group.

    You can use `random_state` for reproducibility.

    .. versionadded:: 1.1.0

    Parameters
    ----------
    n : int, optional
        Number of items to return for each group. Cannot be used with
        `frac` and must be no larger than the smallest group unless
        `replace` is True. Default is one if `frac` is None.
    frac : float, optional
        Fraction of items to return. Cannot be used with `n`.
    replace : bool, default False
        Allow or disallow sampling of the same row more than once.
    weights : list-like, optional
        Default None results in equal probability weighting.
        If passed a list-like then values must have the same length as
        the underlying DataFrame or Series object and will be used as
        sampling probabilities after normalization within each group.
        Values must be non-negative with at least one positive element
        within each group.
    random_state : int, array-like, BitGenerator, np.random.RandomState, optional
        If int, array-like, or BitGenerator (NumPy>=1.17), seed for
        random number generator
        If np.random.RandomState, use as numpy RandomState object.

    Returns
    -------
    Series or DataFrame
        A new object of same type as caller containing items randomly
        sampled within each group from the caller object.

    See Also
    --------
    DataFrame.sample: Generate random samples from a DataFrame object.
    numpy.random.choice: Generate a random sample from a given 1-D numpy
        array.

    Examples
    --------
    >>> df = pd.DataFrame(
    ...     {"a": ["red"] * 2 + ["blue"] * 2 + ["black"] * 2, "b": range(6)}
    ... )
    >>> df
           a  b
    0    red  0
    1    red  1
    2   blue  2
    3   blue  3
    4  black  4
    5  black  5

    Select one row at random for each distinct value in column a. The
    `random_state` argument can be used to guarantee reproducibility:

    >>> df.groupby("a").sample(n=1, random_state=1)
           a  b
    4  black  4
    2   blue  2
    1    red  1

    Set `frac` to sample fixed proportions rather than counts:

    >>> df.groupby("a")["b"].sample(frac=0.5, random_state=2)
    5    5
    2    2
    0    0
    Name: b, dtype: int64

    Control sample probabilities within groups by setting weights:

    >>> df.groupby("a").sample(
    ...     n=1,
    ...     weights=[1, 1, 1, 0, 0, 1],
    ...     random_state=1,
    ... )
           a  b
    5  black  5
    2   blue  2
    0    red  0
    """
    from pandas.core.reshape.concat import concat

    if weights is not None:
        weights = Series(weights, index=self._selected_obj.index)
        ws = [weights.iloc[idx] for idx in self.indices.values()]
    else:
        ws = [None] * self.ngroups

    if random_state is not None:
        random_state = com.random_state(random_state)

    samples = [
        obj.sample(
            n=n, frac=frac, replace=replace, weights=w, random_state=random_state
        )
        for (_, obj), w in zip(self, ws)
    ]

    return concat(samples, axis=self.axis)