pandas - 更改第二级索引的值以显示在第一级索引中的位置

0 投票
2 回答
858 浏览
提问于 2025-04-18 13:17

我该如何将第二级索引的值从

                           PRICE  
TIMESTAMP           HSEC                            
2013-03-15 09:00:29  1     34.480 
2013-03-15 09:00:30  0     34.470  
                     3     34.485  
2013-03-15 09:00:31  0     34.495   
2013-03-15 09:00:35  0     34.485   
2013-03-15 09:00:36 10     34.480  
                    65    

改成

                           PRICE  
TIMESTAMP           HSEC                            
2013-03-15 09:00:29  0     34.480 
2013-03-15 09:00:30  0     34.470  
                     1     34.485  
2013-03-15 09:00:31  0     34.495   
2013-03-15 09:00:35  0     34.485   
2013-03-15 09:00:36  0     34.480  
                     1    

这样'HSEC'就能显示在第一级索引中的行的位置呢?

2 个回答

0

chrisb的回答实际上是有效的。不过,我需要对很多大型数据框进行这个操作,所以速度对我来说很重要。

我找到了一种看起来比较复杂的方法,但运行速度快得多。

runlength = np.array(df.index.labels[0])

runlength = np.append(0,np.diff(runlength))

runlength = np.append(np.nonzero(runlength),len(df.index))
runlength = np.diff(np.append(0,runlength))

cumrunlength = np.cumsum(runlength)
cumrunlength = np.append(0,cumrunlength)
mylabel = df.index.labels[0]
neworder = [x - cumrunlength[mylabel[x]] for x in xrange(len(mylabel))]

df.reset_index(['TIMESTAMP','HSEC'], drop=False, inplace=True)
df['newIndex'] = neworder

df.set_index(['TIMESTAMP','newIndex'],inplace=True)

首先,我检查第一级标签变化的地方。这些变化发生的索引差值让我知道每个连续段的长度,也就是每个独特'TIMESTAMP'条目的行数。然后,通过从一个连续的索引0,1,2,...,n中减去到当前位置为止的连续段的总长度,来确定每个位置。

我对python和pandas还很陌生,所以我不知道如何进行准确的速度比较。我使用了一个简单的计时方法,start_time = time.clock(),然后打印出time.clock() - start_time,'秒',我发现chrisb的代码大约需要4到5秒,而我上面的代码在一个长度为16325的数据框上只需要0.04秒。我猜这可能是因为.groupby()操作像循环一样工作。这样理解对吗?

0

从这些数据开始:

In [119]: df
Out[119]: 
                           PRICE
TIMESTAMP           HSEC        
2013-03-15 09:00:29 1     34.480
2013-03-15 09:00:30 0     34.470
                    3     34.485
2013-03-15 09:00:31 0     34.495
2013-03-15 09:00:35 0     34.485
2013-03-15 09:00:36 10    34.480
                    65    34.480

我的方法是先按第一个层级的索引进行分组,然后用 range 来生成每个组内的位置数组。接着,构建一个元组的列表,以创建一个新的多重索引。

In [120]: positions = df.groupby(level=0).transform(lambda x: range(len(x))).values.ravel()

In [121]: new_index = [(timestamp, position) for ((timestamp, _), position) in 
     ...:                        zip(df.index, positions)]

In [122]: df.index = pd.MultiIndex.from_tuples(new_index)

In [123]: df
Out[123]: 
                        PRICE
2013-03-15 09:00:29 0  34.480
2013-03-15 09:00:30 0  34.470
                    1  34.485
2013-03-15 09:00:31 0  34.495
2013-03-15 09:00:35 0  34.485
2013-03-15 09:00:36 0  34.480
                    1  34.480

撰写回答