熊猫指数:识别连续重复相同值的子范围

Xuk*_*rao 2 python duplicates pandas

问题描述

我正在寻找一种有效的方法来识别pandas Index对象中连续重复相同值的所有子范围.

示例问题

举个简单的例子,考虑以下pandas Index对象:

import pandas as pd
idx = pd.Index(['X', 'C', 'C', 'C', 'Q', 'Q', 'Q', 'Q', 'A', 'P', 'P'])
Run Code Online (Sandbox Code Playgroud)

在这个例子中,值C从位置1到3 Q重复,值从位置4到7 P重复,值从位置9到10重复.然后我试图得到的结果是元组列表(或类似的东西)像这样:

[(1, 3, 'C'), (4, 7, 'Q'), (9, 10, 'P')]
Run Code Online (Sandbox Code Playgroud)

到目前为止尝试过

我一直在试验这个pandas.Index.duplicated房产,但仅凭这一点,我还没有成功地取得理想的结果.

编辑:

非常感谢大家的回答.我有一个后续问题.假设Index它还包含非连续的重复值,如本示例所示(其中value X出现多次):

idx = pd.Index(['X', 'C', 'C', 'C', 'Q', 'Q', 'Q', 'Q', 'X', 'P', 'P'])
Run Code Online (Sandbox Code Playgroud)

你怎么能得到一个忽略这些X值的结果?即如何获得此示例的以下结果:

[(1, 3, 'C'), (4, 7, 'Q'), (9, 10, 'P')]
Run Code Online (Sandbox Code Playgroud)

Max*_*axU 5

这是一种方式:

In [107]: ix = pd.Series(idx.values)

In [108]: [(v.min(), v.max(),k) for k,v in ix.groupby(ix).groups.items() if len(v) > 1]
Out[108]: [(1, 3, 'C'), (9, 10, 'P'), (4, 7, 'Q')]
Run Code Online (Sandbox Code Playgroud)


Bra*_*mon 5

原始问题

哪里idx = pd.Index(['X', 'C', 'C', 'C', 'Q', 'Q', 'Q', 'Q', 'A', 'P', 'P']).

有点不同寻常,但应该工作,而且似乎也明显更快:

# Get a new Index which is the unique duplicated values in `idx`
un = idx[idx.duplicated(keep=False)].unique()

# Call `get_loc` on `idx` for each member of `un` above  
# `np.where` gets position of True in boolean Index
res = []
for i in un:
    w = np.where(idx.get_loc(i))[0]
    # w[0], w[-1] analogous to v.min(), v.max() from @MaxU's answer
    res.append((w[0], w[-1], i))

print(res)
# [(1, 3, 'C'), (4, 7, 'Q'), (9, 10, 'P')]
Run Code Online (Sandbox Code Playgroud)

定时:

%timeit myanswer()
105 µs ± 3.19 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit maxu()
1.21 ms ± 116 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Run Code Online (Sandbox Code Playgroud)

取消注释:

un = idx[idx.duplicated(keep=False)].unique()
res = []
for i in un:
    w = np.where(idx.get_loc(i))[0]
    res.append((w[0], w[-1], i))
Run Code Online (Sandbox Code Playgroud)

编辑问题

哪里idx = pd.Index(['X', 'C', 'C', 'C', 'Q', 'Q', 'Q', 'Q', 'X', 'P', 'P']).

要到达un这里,首先得到一个布尔索引,当一个值等于它之前或之后的值时为True,否则为False.这与idx.duplicated(keep=False)第一部分类似.

b = (Series(idx).shift() == idx) | (Series(idx).shift(-1) == idx)
un = idx[b].unique()
# Rest should be the same
Run Code Online (Sandbox Code Playgroud)