分组、排序并检测行之间的变化

问题描述 投票:0回答:1

我有一个数据框。我想按 col1 分组,按 col3 排序并检测 col2 中行与行之间的变化。

这是我的例子:

import pandas as pd
import datetime

my_df = pd.DataFrame({'col1': ['a', 'a', 'a', 'b', 'b', 'b'],
                      'col2': [2, 2, 3, 5, 5, 5],
                      'col3': [datetime.date(2023, 2, 1),
                               datetime.date(2023, 3, 1),
                               datetime.date(2023, 4, 1),
                               datetime.date(2023, 2, 1),
                               datetime.date(2023, 3, 1),
                               datetime.date(2023, 4, 1)]})

my_df.sort_values(by=['col3'], inplace=True)
my_df_temp = my_df.groupby('col1')['col2'].apply(
    lambda x: x != x.shift(1)
).reset_index(name='col2_change')

这是我的数据框的外观:

  col1  col2        col3
0    a     2  2023-02-01
1    a     2  2023-03-01
2    a     3  2023-04-01
3    b     5  2023-02-01
4    b     5  2023-03-01
5    b     5  2023-04-01

结果如下:

  col1  level_1  col2_change
0    a        0         True
1    a        1        False
2    a        2         True
3    b        3         True
4    b        4        False
5    b        5        False

这显然是不正确的。我做错了什么?

pandas group-by row
1个回答
0
投票

首先,你的问题并不明显,为了清楚起见,你应该提供预期的输出。

我想您想添加一个新列并保持原来现有的列不变。为此,您需要使用

groupby.transform
:

my_df['col2_change'] = (my_df
                        .groupby('col1')['col2']
                        .transform(lambda x: x != x.shift())
                       )

带有

groupby.shift
的变体:

my_df['col2_change'] = (my_df
                        .groupby('col1')['col2']
                        .shift().ne(my_df['col2'])
                       )

此外,如果您不想将组的第一个值映射为

True
,您可以执行 double
shift
:

my_df['col2_change2'] = (my_df
                         .groupby('col1')['col2']
                         .transform(lambda x: x.ne(x.shift(-1))
                                               .shift(fill_value=False))
                        )

注意。双移优于

bfill
,因为它会错误地填充内部 NaN(如果有)。

或使用

duplicated
where
:

my_df['col2_change2'] = (my_df
                         .groupby('col1')['col2']
                         .transform(lambda x: x != x.shift())
                         .where(my_df['col1'].duplicated(), False)
                       )

输出:

  col1  col2        col3  col2_change  col2_change2
0    a     2  2023-02-01         True         False
3    b     5  2023-02-01         True         False
1    a     2  2023-03-01        False         False
4    b     5  2023-03-01        False         False
2    a     3  2023-04-01         True          True
5    b     5  2023-04-01        False         False
© www.soinside.com 2019 - 2024. All rights reserved.