python - 性能警告:在没有级别参数的情况下丢弃非 lexsorted 多索引可能会影响性能。如何摆脱它?

我有以下代码行

end_df['Soma Internet'] = end_df.iloc[:,end_df.columns.get_level_values(1) == 'Internet'].drop('site',axis=1).sum(axis=1)

基本上,它通过特定的 1 级列过滤我的多索引 df。删除一些不想要的列。并做所有其他的总和。

我看了看一些文档和其他问题。但我不太明白是什么导致了警告,我也很想重写这段代码,所以我把它去掉了。

回答1

让我们尝试一个示例(为简单起见,没有数据):

# Column MultiIndex.
idx = pd.MultiIndex(levels=[['Col1', 'Col2', 'Col3'], ['subcol1', 'subcol2']], 
                    codes=[[2, 1, 0], [0, 1, 1]])

df = pd.DataFrame(columns=range(len(idx)))
df.columns = idx
print(df)
Col3    Col2    Col1
subcol1 subcol2 subcol2

显然,列 MultiIndex 未排序。我们可以通过以下方式进行检查:

print(df.columns.is_monotonic)
False

这很重要,因为如果索引已排序,Pandas 会更快地执行索引查找和其他操作,因为它可以使用假定已排序顺序的操作并且速度更快。事实上,如果我们尝试删除一列:

df.drop('Col1', axis=1)
PerformanceWarning: dropping on a non-lexsorted multi-index without a level parameter may impact performance.
  df.drop('Col1', axis=1)

相反,如果我们在删除之前对索引进行排序,警告就会消失:

print(df.sort_index(axis=1))

# Index is now sorted in lexical order.
    Col1    Col2    Col3
subcol2 subcol2 subcol1
# No warning here.
df.sort_index(axis=1).drop('Col1', axis=1)

编辑(见评论):正如警告所暗示的,当我们没有指定我们想要删除列的级别时,就会发生这种情况。这是因为要删除列,pandas 必须遍历整个未排序的索引(发生在 https://github.com/pandas-dev/pandas/blob/98ca9f05b8e04b327f2a0a0d82e89dfcb4eac00a/pandas/core/indexes/multi.py#L2280)。通过指定它,我们不需要这样的遍历:

# Also no warning.
df.drop('Col1', axis=1, level=0)

然而,一般来说,这个问题更多地与行索引有关,因为通常列多索引要小得多。但对于更大的索引和数据框,绝对要记住这一点。事实上,这与按索引切片和查找特别相关。在这些情况下,您希望对索引进行排序以获得更好的性能。