在Pandas中是什么原因导致“索引超过lexsort深度”警告?

qhhrdooz  于 2023-04-04  发布在  其他
关注(0)|答案(4)|浏览(135)

我正在使用df.loc[(key1, key2)]索引一个大型的多索引Pandas df。有时我会得到一个系列(如预期的那样),但其他时候我会得到一个dataframe。我试图隔离导致后者的情况,但到目前为止,我所能看到的是它与得到PerformanceWarning: indexing past lexsort depth may impact performance警告相关。
我想复制它来发布在这里,但我不能生成另一个案例,给我同样的警告。这是我的尝试:

def random_dates(start, end, n=10):
    start_u = start.value//10**9
    end_u = end.value//10**9
    return pd.to_datetime(np.random.randint(start_u, end_u, n), unit='s')

np.random.seed(0)
df = pd.DataFrame(np.random.random(3255000).reshape(465000,7))  # same shape as my data
df['date'] = random_dates(pd.to_datetime('1990-01-01'), pd.to_datetime('2018-01-01'), 465000)
df = df.set_index([0, 'date'])
df = df.sort_values(by=[3])  # unsort indices, just in case
df.index.lexsort_depth
> 0
df.index.is_monotonic
> False
df.loc[(0.9987185534991936, pd.to_datetime('2012-04-16 07:04:34'))]
# no warning

所以我的问题是:是什么原因导致此警告?如何人为诱导?

yuvru6vn

yuvru6vn1#

TL;DR:您的索引未排序,这会严重影响性能。

使用df.sort_index()对DataFrame的索引进行排序,以解决警告并提高性能。
实际上,我已经在我的文章中详细描述了这一点:Select rows in pandas MultiIndex DataFrame(在“问题3”下)。
为了繁殖,

mux = pd.MultiIndex.from_arrays([
    list('aaaabbbbbccddddd'),
    list('tuvwtuvwtuvwtuvw')
], names=['one', 'two'])

df = pd.DataFrame({'col': np.arange(len(mux))}, mux)

         col
one two     
a   t      0
    u      1
    v      2
    w      3
b   t      4
    u      5
    v      6
    w      7
    t      8
c   u      9
    v     10
d   w     11
    t     12
    u     13
    v     14
    w     15

您会注意到第二个级别没有正确排序。
现在,尝试索引特定的横截面:

df.loc[pd.IndexSlice[('c', 'u')]]
PerformanceWarning: indexing past lexsort depth may impact performance.
  # encoding: utf-8

         col
one two     
c   u      9

您将看到xs的相同行为:

df.xs(('c', 'u'), axis=0)
PerformanceWarning: indexing past lexsort depth may impact performance.
  self.interact()

         col
one two     
c   u      9

this timing test I once did支持的文档似乎表明,处理未排序的索引会导致速度减慢-索引是O(N)时间,而它可能/应该是O(1)。
如果你在切片之前对索引进行排序,你会注意到不同之处:

df2 = df.sort_index()
df2.loc[pd.IndexSlice[('c', 'u')]]

         col
one two     
c   u      9

%timeit df.loc[pd.IndexSlice[('c', 'u')]]
%timeit df2.loc[pd.IndexSlice[('c', 'u')]]

802 µs ± 12.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
648 µs ± 20.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

最后,如果想知道索引是否已排序,请使用MultiIndex.is_lexsorted进行检查。

df.index.is_lexsorted()
# False

df2.index.is_lexsorted()
# True

至于你的问题,如何诱导这种行为,简单地排列索引就足够了。如果你的索引是唯一的,这是可行的:

df2 = df.loc[pd.MultiIndex.from_tuples(np.random.permutation(df2.index))]

如果你的索引不是唯一的,先添加一个cumcount艾德级别,

df.set_index(
    df.groupby(level=list(range(len(df.index.levels)))).cumcount(), append=True) 
df2 = df.loc[pd.MultiIndex.from_tuples(np.random.permutation(df2.index))]
df2 = df2.reset_index(level=-1, drop=True)
nwsw7zdq

nwsw7zdq2#

根据pandas高级索引(排序多索引)
在更高维的对象上,如果其他轴具有MultiIndex,则可以按级别对它们进行排序
并且:
即使数据没有排序,索引也可以工作,但效率会很低**(并显示PerformanceWarning)**。它还会返回数据的副本而不是视图:
根据它们,您可能需要确保索引正确排序。

p4rjhz4m

p4rjhz4m3#

系列与 Dataframe 输出:我也遇到了同样的问题,有时df.loc[(index1, index2)]的输出是一个系列,有时是一个 Dataframe 。我发现这是由重复的索引引起的。如果 Dataframe 有一些重复的索引,df.loc[(index1, index2)]的输出是一个 Dataframe ,否则是一个系列。

u7up0aaq

u7up0aaq4#

在我的案例中,PerformanceWarning:索引超过LexSort深度可能会影响DF上的重复索引的性能。
案例:尝试在每个sheetname的循环中读取带有pandas的excel文件
在具有重复索引的工作表中给出:性能警告:索引超过lexsort深度可能会影响性能

相关问题