我有一个数据框。我想按 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
这显然是不正确的。我做错了什么?
首先,你的问题并不明显,为了清楚起见,你应该提供预期的输出。
我想您想添加一个新列并保持原来现有的列不变。为此,您需要使用
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