Pandas 分组依据 - 按时间和条件分隔

Pandas Group By - Separate by Time and Condition

我有一个数据框,我试图根据两个条件创建子 event_ids - 时间和标志。标志是当人 >= 600 时,创建一个新的子组。

数据看起来像这样:

    | event_id   |  timestamp |  people |
    |  abc       |  12:00     |   1     |
    |  abc       |  12:01     |   3     |
    |  abc       |  12:02     |   5     |
    |  abc       |  12:04     |   600   |
    |  abc       |  12:10     |   4     |
    |  abc       |  12:15     |   7     |
    |  abc       |  12:20     |   1700  |
    |  abc       |  12:30     |   1     |
    |  abc       |  12:31     |   1     |
    |  xyz       |  12:32     |   1     |
    |  xyz       |  12:40     |   750   |
    |  xyz       |  12:50     |   1     |

我想要的结果是这样的:

    | event_id   |  timestamp |  people |  subgroup  |
    |  abc       |  12:00     |   1     |      A     |
    |  abc       |  12:01     |   3     |      A     |
    |  abc       |  12:02     |   5     |      A     |
    |  abc       |  12:04     |   600   |      A     |
    |  abc       |  12:10     |   4     |      B     |
    |  abc       |  12:15     |   7     |      B     |
    |  abc       |  12:20     |   1700  |      B     |
    |  abc       |  12:30     |   1     |      C     |
    |  abc       |  12:31     |   1     |      C     |
    |  xyz       |  12:32     |   1     |      A     |
    |  xyz       |  12:40     |   750   |      A     |
    |  xyz       |  12:50     |   1     |      B     |

所以它需要某种分组依据来解释不同的 event_ids(这里是 abc 和 xyz,但在我的真实数据集中有数百万)。数据是按时间排序的,在确定分组时行顺序很重要 - 两个标志之间 event_id 的行在一个子组中。每个子组都属于 event_id,子组的计数重新开始以获得新的 event_id。

很想看到 any/all 个想法,我很困惑,但现在正在玩 lambda 函数。

from string import ascii_uppercase

m = dict(enumerate(ascii_uppercase))

def trickery(x):
    c = (x.values >= 600)[::-1].cumsum()[::-1]
    return c.max() - c

df.assign(subgroup=df.groupby('event_id').people.transform(trickery).map(m))

   event_id timestamp  people subgroup
0       abc     12:00       1        A
1       abc     12:01       3        A
2       abc     12:02       5        A
3       abc     12:04     600        A
4       abc     12:10       4        B
5       abc     12:15       7        B
6       abc     12:20    1700        B
7       abc     12:30       1        C
8       abc     12:31       1        C
9       xyz     12:32       1        A
10      xyz     12:40     750        A
11      xyz     12:50       1        B
df.groupby('event_id').people.apply(lambda x :(x>=600).shift().fillna(0).cumsum()).\
    map({0:'A',1:'B',2:'C'})
Out[207]: 
0     A
1     A
2     A
3     A
4     B
5     B
6     B
7     C
8     C
9     A
10    A
11    B
Name: people, dtype: object

然后你只需要把它赋值回来。