在python中将值的顺序索引减少为每个值的一组顺序范围的最快方法

在python中将值的顺序索引减少为每个值的一组顺序范围的最快方法,python,pandas,performance,Python,Pandas,Performance,我有一个大熊猫数据帧,索引是连续的整数。该列对应于该位置的值,例如: a = pd.DataFrame(index=range(7),data = [1.3,1.3,1.3,0.4,0.6,0.6,1.3], columns=['Values']) Values 0 1.3 1 1.3 2 1.3 3 0.4 4 0.6 5 0.6 6 1.3 是否有一种快速的方法将其减少为一组连续范围: start end Values 0

我有一个大熊猫数据帧,索引是连续的整数。该列对应于该位置的值,例如:

a = pd.DataFrame(index=range(7),data = [1.3,1.3,1.3,0.4,0.6,0.6,1.3], columns=['Values'])
     Values
0    1.3
1    1.3
2    1.3
3    0.4
4    0.6
5    0.6
6    1.3
是否有一种快速的方法将其减少为一组连续范围:

start    end    Values
0        3        1.3
3        4        0.4
4        6        0.6
6        7        1.3
我已经排除了逐行迭代太慢的可能性。从中得到一些启发,我在每个唯一值上使用了enumerate+groupby模式:

for val in set(a['Values'].values):
    index = list(a[list(a['Values'] == val)].index.values)
    for _, g in groupby(index, key=lambda n, c=count(): n-next(c)):
        l = list(g)
        print(l[0], l[-1]+1, val)

3    4    0.4
0    3    1.3
6    7    1.3
4    6    0.6

然后我可以存储和排序。是否有任何方法可以改进此功能以提高python的性能?

您可以使用
idxmin
idxmax
创建一个助手系列和组:

s = a['Values'].ne(a['Values'].shift()).cumsum().rename(None)
d = dict(zip(['idxmin','idxmax'],['start','end']))

a.groupby([s,'Values'])['Values'].agg(['idxmin','idxmax']).rename(columns=d)


请注意,由于数据帧中不存在该索引,因此对于弹性值
1.3
,这不会给出7结尾。

使用
diff
cumsum
创建
groupby
键,do
groupby

b=a.reset_index().groupby(a.Values.diff().ne(0).cumsum()).\
      agg(start=('index','min'),
          end=('index',lambda x : x.max()+1),
          Values=('Values','first'))
        start  end  Values
Values                    
1           0    3     1.3
2           3    4     0.4
3           4    6     0.6
4           6    7     1.3

为什么在索引7不存在的情况下,您希望最后一行以7结尾。您是对的,如果是6就可以了。只是出于从python列表中获取切片的习惯。
b=a.reset_index().groupby(a.Values.diff().ne(0).cumsum()).\
      agg(start=('index','min'),
          end=('index',lambda x : x.max()+1),
          Values=('Values','first'))
        start  end  Values
Values                    
1           0    3     1.3
2           3    4     0.4
3           4    6     0.6
4           6    7     1.3