有没有办法在不排序多重索引DataFrame列的情况下避免lexsort警告?

1 投票
1 回答
49 浏览
提问于 2025-04-14 17:51

我知道在使用MultiIndexed的pandas DataFrame时,排序列(或索引)是有一些性能上的原因的。不过,我自己有一些“用户界面”的考虑,想要保持列的特定顺序。有没有办法避免出现以下警告,而不需要改变列的顺序呢?

PerformanceWarning: indexing past lexsort depth may impact performance.

如果没有办法干净利落地做到这一点,至少有没有什么方法可以暂时排序列,然后再把它们的顺序恢复到操作之前的样子呢?

这里有一些完整的代码:

import pandas as pd

N = 3
rangeN = list(range(1, N + 1))
index = pd.MultiIndex.from_product(
    [rangeN, rangeN], names=["level1", "level2"]
)
columns = [
    (
        "col_B",
        "col_B.1",
    ),
    (
        "col_B",
        "col_B.2",
    ),
]
components = range(1, 3)
columns += [("col_A", "col_A.1", f"col_A.1.{c}") for c in components]
columns += [("col_A", "col_A.2", f"col_A.2.{c}") for c in components]
columns = pd.MultiIndex.from_tuples(columns)
df = pd.DataFrame(columns=columns, index=index)

df.loc[:, ("col_B", "col_B.2",)] = 7  # Warning thrown here

print(df)

它返回

                col_B             col_A                              
              col_B.1 col_B.2   col_A.1             col_A.2          
                  NaN     NaN col_A.1.1 col_A.1.2 col_A.2.1 col_A.2.2
level1 level2                                                        
1      1          NaN       7       NaN       NaN       NaN       NaN
       2          NaN       7       NaN       NaN       NaN       NaN
       3          NaN       7       NaN       NaN       NaN       NaN
2      1          NaN       7       NaN       NaN       NaN       NaN
       2          NaN       7       NaN       NaN       NaN       NaN
       3          NaN       7       NaN       NaN       NaN       NaN
3      1          NaN       7       NaN       NaN       NaN       NaN
       2          NaN       7       NaN       NaN       NaN       NaN
       3          NaN       7       NaN       NaN       NaN       NaN
c:\users\tfovid\draft.py:31: PerformanceWarning: indexing past lexsort depth may impact performance.
  df.loc[:, ("col_B", "col_B.2",)] = 7

1 个回答

2

我注意到你在列索引中有3个层级,所以在.loc后面加上slice(None)会有帮助:

df.loc[:, ("col_B", "col_B.2", slice(None))] = 7
print(df)

这样打印出来就不会有警告了:

                col_B             col_A                              
              col_B.1 col_B.2   col_A.1             col_A.2          
                  NaN     NaN col_A.1.1 col_A.1.2 col_A.2.1 col_A.2.2
level1 level2                                                        
1      1          NaN       7       NaN       NaN       NaN       NaN
       2          NaN       7       NaN       NaN       NaN       NaN
       3          NaN       7       NaN       NaN       NaN       NaN
2      1          NaN       7       NaN       NaN       NaN       NaN
       2          NaN       7       NaN       NaN       NaN       NaN
       3          NaN       7       NaN       NaN       NaN       NaN
3      1          NaN       7       NaN       NaN       NaN       NaN
       2          NaN       7       NaN       NaN       NaN       NaN
       3          NaN       7       NaN       NaN       NaN       NaN

撰写回答