Pandas Dataframe拆分为会话

时间:2013-07-10 10:38:44

标签: python pandas dataframe

这是我question的扩展名。

使其更简单让我们假设我有一个pandas数据帧如下。

df = pd.DataFrame([[1.1, 1.1, 2.5, 2.6, 2.5, 3.4,2.6,2.6,3.4], list('AAABBBBAB'), [1.1, 1.7, 2.5, 2.6, 3.3, 3.8,4.0,4.2,4.3]]).T
df.columns = ['col1', 'col2','col3']

dataframe:

  col1 col2 col3
0  1.1    A  1.1
1  1.1    A  1.7
2  2.5    A  2.5
3  2.6    B  2.6
4  2.5    B  3.3
5  3.4    B  3.8
6  2.6    B    4
7  2.6    A  4.2
8  3.4    B  4.3

我想根据某些条件对此进行分组。逻辑基于col1 col2值和col3的累积差异:

  1. 转到col1并查找其他相同值的匹配项。
  2. 在我的情况下,col1的第一个值是'1.1',并且它们在第2行的值是相同的。
  3. 然后检查col2值,如果它们相似,则得到col 3的累积差异。
  4. 如果累积差异大于0.5,则将其标记为新会话。
  5. 如果col1值相同但col2值不同,则将它们标记为新会话
  6. 预期产出:

       col1 col2 col3 session
    0  1.1    A  1.1  0
    1  1.1    A  1.7  1
    2  2.5    A  2.5  2
    3  2.6    B  2.6  4
    4  2.5    B  3.3  3
    5  3.4    B  3.8  7
    6  2.6    B    4  5
    7  2.6    A  4.2  6
    8  3.4    B  4.3  7
    

1 个答案:

答案 0 :(得分:7)

与您链接的优秀答案一样;)首先创建会话号:

In [11]: g = df.groupby(['col1', 'col2'])

In [12]: df['session_number'] = g['col3'].apply(lambda s: (s - s.shift(1) > 0.5).fillna(0).cumsum(skipna=False))

然后我想你想要这些列的set_index,这对于许多用例来说已经足够了(虽然它可能值得做sort):

In [13]: df1 = df.set_index(['col1', 'col2', 'session_number'])

In [14]: df1
Out[14]:
                         col3
col1 col2 session_number
1.1  A    0               1.1
          1               1.7
2.5  A    0               2.5
2.6  B    0               2.6
2.5  B    0               3.3
3.4  B    0               3.8
2.6  B    1                 4
     A    0               4.2
3.4  B    0               4.3

如果你真的想要,你可以拿出会话号码:

In [15]: g1 = df.groupby(['col1', 'col2', 'session_number'])  # I think there is a slightly neater way, but I forget..

In [16]: df1['session'] = g1.apply(lambda x: 1).cumsum()  # could -1 here if it matters

In [17]: df1
Out[17]:
                         col3  session
col1 col2 session_number
1.1  A    0               1.1        1
          1               1.7        2
2.5  A    0               2.5        3
2.6  B    0               2.6        6
2.5  B    0               3.3        4
3.4  B    0               3.8        8
2.6  B    1                 4        7
     A    0               4.2        5
3.4  B    0               4.3        8

如果你想在列中(如你的问题中那样)reset_index,你可以删除会话列:

In [18]: df1.reset_index()
Out[18]:
   col1 col2  session_number col3  session
0   1.1    A               0  1.1        1
1   1.1    A               1  1.7        2
2   2.5    A               0  2.5        3
3   2.6    B               0  2.6        6
4   2.5    B               0  3.3        4
5   3.4    B               0  3.8        8
6   2.6    B               1    4        7
7   2.6    A               0  4.2        5
8   3.4    B               0  4.3        8