如何根据列分组重新索引 python 数据框

how to reindex python dataframe based on column grouping

我是 python 的新手。请协助。我有一个包含数千行的巨大数据框。 df 的示例如下所示。

        STATE        VOLUME
INDEX           
1       on         10
2       on         15
3       on         10
4       off        20
5       off        30
6       on         15
7       on         20
8       off        10
9       off        30
10      off        10
11      on         20
12      off        25

我希望能够根据 'state' 列索引此数据,以便第一批 'on' 和 'off' 注册为索引 1,下一批 'on' 和 'off' 注册为索引 2 等等...我希望能够 select 一组数据,如果我 select 索引为 1 的行。

       ID        VOLUME
INDEX           
1       on         10
1       on         15
1       on         10
1       off        20
1       off        30
2       on         15
2       on         20
2       off        10
2       off        30
2       off        10
3       on         20
3       off        25

您可以尝试使用 pd.Series.shift and pd.Series.cumsum:

df.index=((df.STATE.shift(-1) != df.STATE)&df.STATE.eq('off')).shift(fill_value=0).cumsum()+1

np.where 相同:

temp=pd.Series(np.where((df.STATE.shift(-1) != df.STATE)&(df.STATE.eq('off')),1,0))
df.index=temp.shift(1,fill_value=0).cumsum().astype(int).add(1)

输出:

df
  STATE  VOLUME
1    on      10
1    on      15
1    on      10
1   off      20
1   off      30
2    on      15
2    on      20
2   off      10
2   off      30
2   off      10
3    on      20
3   off      25

说明: 使用 (df.STATE.shift(-1) != df.STATE)&df.STATE.eq('off'),当它变为 'off':

时,您将得到一个带有最后一个值的掩码
(df.STATE.shift(-1) != df.STATE)&df.STATE.eq('off')

1     False
2     False
3     False
4     False
5      True
6     False
7     False
8     False
9     False
10     True
11    False
12     True

然后你移动它以包括最后一个值,然后你做一个 cumsum() 知道 True: 1False: 0:

((df.STATE.shift(-1) != df.STATE)&df.STATE.eq('off')).shift(fill_value=0)
1         0
2     False
3     False
4     False
5     False
6      True
7     False
8     False
9     False
10    False
11     True
12    False

((df.STATE.shift(-1) != df.STATE)&df.STATE.eq('off')).shift(fill_value=0).cumsum()
1     0
2     0
3     0
4     0
5     0
6     1
7     1
8     1
9     1
10    1
11    2
12    2

最后将 1(+1) 添加到索引中,以获得所需的结果。

您可以尝试 pd.Series.eq with pd.Series.shift and take cumsum using pd.Series.cumsum

df.index = (df['STATE'].eq('off').shift() & df['STATE'].eq('on')).cumsum() + 1
df.index.name = 'INDEX'

      STATE  VOLUME
INDEX
1        on      10
1        on      15
1        on      10
1       off      20
1       off      30
2        on      15
2        on      20
2       off      10
2       off      30
2       off      10
3        on      20
3       off      25

详情

我们的想法是找到 off 后跟 on 的位置。

# (df['STATE'].eq('off').shift() & df['STATE'].eq('on')).cumsum() + 1

      eq(off).shift  eq(on)  eq(off).shift & eq(on)
INDEX
1               NaN    True                   False
2             False    True                   False
3             False    True                   False
4             False   False                   False
5              True   False                   False
6              True    True                    True
7             False    True                   False
8             False   False                   False
9              True   False                   False
10             True   False                   False
11             True    True                    True
12            False   False                   False