【问题标题】:how to reindex python dataframe based on column grouping如何根据列分组重新索引python数据框
【发布时间】:2020-11-13 22:53:40
【问题描述】:

我是 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

我希望能够根据“状态”列索引此数据,以便第一批“开”和“关”注册为索引 1,下一批“开”和“关”注册为索引 2 等等……如果我选择索引为 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

【问题讨论】:

  • 批次总是 5 个观察值吗?您能否澄清“行没有相似的间距”是什么意思?你能分享一些你已经尝试过的代码吗?
  • @heilala 它不仅仅是 5 个观察结果。我只取了一部分数据,因为它包含数千行具有“开”和“关”批次的行
  • 你有 5 次索引 1,5 次索引 2...我的意思是问,索引总是以 5 个为一组吗?或者您如何确定哪些观察结果属于同一批次?
  • 第一个问题很酷。欢迎来到Stack Overflow ;)

标签: python pandas indexing rows


【解决方案1】:

你可以用pd.Series.shiftpd.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'),当它变为“关闭”时,您将获得一个带有最后一个值的掩码:

(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

然后你把它转移到最后一个值,然后你知道True: 1False: 0做一个cumsum()

((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) 添加到索引中,以获得所需的结果。

【讨论】:

    【解决方案2】:

    你可以用pd.Series.eqpd.Series.shift试试这个,然后用pd.Series.cumsum取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
    

    【讨论】:

    • 不错的答案@Ch3steR +1。
    猜你喜欢
    • 2014-11-29
    • 2017-03-27
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多