我有以下代码:
import pandas as pd
series_source = pd.Series([1, 2, 3, 4], dtype=int)
normal_index = pd.Series([True, False, True, True], dtype=bool)
big_index = pd.Series([True, False, True, True, False, True], dtype=bool)
# Both indexes give back: pd.Series([1, 2, 3, 4], dtype=int)
# no warnings are raised!
assert (series_source[normal_index] == series_source[big_index]).all()
df_source = pd.DataFrame(
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
)
# no warning - works as expected: grabs rows 0, 2, and 3
df_normal_result = df_source[normal_index]
# UserWarning: Boolean Series key will be reindexed to match DataFrame index.
# (but still runs)
df_big_result = df_source[big_index]
# passes - they are equivalent
assert df_normal_result.equals(df_big_result)
print("Complete")
为什么使用 索引series_source
不会big_index
引发警告,即使大索引的值比源多? pandas 在后台做了什么来执行 Series 索引?
(与索引相比df_source
,会引发明确警告,big_index
需要重新索引才能使操作正常工作。)
在索引文档中,它声称:
使用布尔向量来索引 Series 的方式与 NumPy ndarray 完全相同
然而,如果我这样做
import numpy as np
a = np.array([1, 2, 3, 4, 5])
b = np.array([True, False, True, True, False])
c = np.array([True, False, True, True, False, True, True])
# returns an ndarray of [1,3, 4] as expected
print(a[b])
# raises IndexError: boolean index did not match indexed array along axis 0;
# size of axis is 5 but size of corresponding boolean axis is 7
print(a[c])
因此,此功能似乎与 Numpy 不匹配,正如文档所述。发生了什么?
(我的版本是pandas==2.2.2
和numpy==2.0.0
。)
因为索引Series首先与被索引的DataFrame/Series的索引对齐。
简而言之,pandas 正在做:
系列示例:
如果你改变索引系列的索引,你实际上可以自己观察到这一点:
输出:
尽管前两个值为 ,但输出中仍有 4 行
False
。重新索引后,布尔值为[True, True, True, True]
。在这种情况下你应该收到警告:
请注意,如果无法完成对齐,则会引发错误,就像在 numpy 中一样:
为什么 DataFrame[Series] 会出现这种情况,而 Series[Series] 不会出现这种情况?
因为有一个对 DataFrame[Series] 的检查
澄清我从@mozway 的回答中了解到的情况:
当使用
pd.Series
或pd.DataFrame
索引pd.Series[bool]
时,pandas 会将源系列中的值的标签(或源数据框中的行的标签)与索引系列中的标签进行匹配。此过程通过以下方法在内部完成reindex
:bool_series.reindex(source.index)
。请注意,如果标签位于源中但不在布尔索引器中,则无法重新建立索引,因此程序将引发错误。
如果源是数据框,并且索引布尔系列的标签与源数据框的标签不完全匹配(
source_df.index != bool_series.index
),则程序将发出警告,表明将重新编制索引。但是,如果源是系列,并且标签不完全匹配(source_series.index != bool_series.index
),则不会发出警告(它只会默默地重新索引布尔系列)。这只是一个实现细节。