【问题标题】:Apply boolean mask only to indexed portion of a dataframe column仅将布尔掩码应用于数据框列的索引部分
【发布时间】:2021-07-15 21:55:21
【问题描述】:

我有一个包含一些列的数据框:

>>> np.random.seed(0xFEE7)
>>> df = pd.DataFrame({'A': np.random.randint(10, size=10), 
                       'B': np.random.randint(10, size=10),
                       'C': np.random.choice(['A', 'B'], size=10)})
>>> df
   A  B  C
0  0  0  B
1  4  0  B
2  6  6  A
3  8  3  B
4  0  2  A
5  8  4  A
6  4  1  B
7  8  7  A
8  4  4  A
9  1  1  A

我还有一个布尔系列匹配df的部分索引:

>>> g = df.groupby('C').get_group('A')
>>> ser = g['B'] > 5
>>> ser
2     True
4    False
5    False
7     True
8    False
9    False
Name: B, dtype: bool

我希望能够使用serdf 设置或提取数据。例如:

>>> df.loc[ser, 'A'] -= 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\jfoxrabinovitz\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexing.py", line 1762, in __getitem__
    return self._getitem_tuple(key)
  File "C:\Users\jfoxrabinovitz\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexing.py", line 1289, in _getitem_tuple
    retval = getattr(retval, self.name)._getitem_axis(key, axis=i)
  File "C:\Users\jfoxrabinovitz\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexing.py", line 1914, in _getitem_axis
    return self._getbool_axis(key, axis=axis)
  File "C:\Users\jfoxrabinovitz\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexing.py", line 1782, in _getbool_axis
    key = check_bool_indexer(labels, key)
  File "C:\Users\jfoxrabinovitz\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexing.py", line 2317, in check_bool_indexer
    raise IndexingError(
pandas.core.indexing.IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).

这个错误是有道理的,因为ser 的长度与df 的长度不同。如何告诉数据框更新与ser 的索引匹配并设置为True 的行?

具体来说,我希望只修改索引 2 和 7 处的条目:

>>> df   # after modification
   A  B  C
0  0  0  B
1  4  0  B
2  3  6  A
3  8  3  B
4  0  2  A
5  8  4  A
6  4  1  B
7  5  7  A
8  4  4  A
9  1  1  A

【问题讨论】:

  • 您可能需要df.loc[ser[ser].index,'A'] 来分配值而不是整个ser.index,因为其他值是假的,不确定预期 - 因此评论:-)
  • @anky。感谢您指出了这一点。我已经更新了问题,期待您的回答,因为您的评论正是我想要的。
  • 我很难想象上面的Series一开始就无法基于整个DataFrame创建一个类似索引的布尔Series的场景。 IE。以上等价于掩码df.C.eq('A') &amp; df.B.gt(5)。此外,如果您有重复的索引,使用 ser 可能会出现问题。
  • @ALollz。请写下来作为答案。我最喜欢的是 XY'd

标签: python pandas indexing mask


【解决方案1】:

我想你可以在loc 中添加索引到ser,因为它们都来自一个共同的索引。

df.loc[ser.index, 'A'] -= 3

正如@Shubham Sharma 所评论的,OP 只需要过滤True 值。这种方法使用'A' 获取所有索引。

@anky 提供了一种方法:

df.loc[ser[ser].index, 'A'] -= 3

【讨论】:

  • 聪明的想法 +1 但您还需要过滤索引以仅包含 True 值,否则这将更新所有值。像df.loc[ser[ser].index, 'A'] -= 3 这样的东西应该可以工作
  • ser[ser].index 可能会这样做
【解决方案2】:

由于ser 的索引与原始数据帧不匹配,您会收到该错误。

你可以通过两种方式解决它:

要么使用 series.reindexfill_valueFalse(布尔值),然后使用 loc,以便对齐索引。

df.loc[ser.reindex(df.index,fill_value=False),'A'] = ... #setvalue

或者您可以对ser 系列进行布尔索引,使其仅返回True 值并授予您可以与loc 一起使用的索引:

df.loc[ser[ser].index,'A'] = ... #setvalue

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-10
    • 2013-07-07
    • 2018-05-11
    • 1970-01-01
    • 2020-01-14
    • 2020-02-14
    • 2016-11-22
    • 2021-02-16
    相关资源
    最近更新 更多