如何根据Pandas中另一列值的变化分组到不同的日期

uxh89sit  于 2022-12-02  发布在  其他
关注(0)|答案(1)|浏览(90)

我有这样的数据

df = pd.DataFrame({'ID': [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2],
 'DATE': ['1/1/2015','1/2/2015', '1/3/2015','1/4/2015','1/5/2015','1/6/2015','1/7/2015','1/8/2015',
  '1/9/2016','1/2/2015','1/3/2015','1/4/2015','1/5/2015','1/6/2015','1/7/2015'],
 'CD': ['A','A','A','A','B','B','A','A','C','A','A','A','A','A','A']})

我想做的是按ID和CD分组,并获得每个更改的开始和停止更改。我尝试使用groupby和agg函数,但它将所有A分组在一起,即使它们需要分开,因为在2个A之间有B。

df1 = df.groupby(['ID','CD'])
df1 = df1.agg(
    Start_Date = ('Date',np.min),
    End_Date=('Date', np.min)
).reset_index()

我得到的是:

我希望有人能帮助我得到我需要的结果。我正在寻找的是:

f87krz0w

f87krz0w1#

使grouper用于分组

grouper = df['CD'].ne(df['CD'].shift(1)).cumsum()

grouper

0     1
1     1
2     1
3     1
4     2
5     2
6     3
7     3
8     4
9     5
10    5
11    5
12    5
13    5
14    5
Name: CD, dtype: int32

然后对grouper使用groupby

df.groupby(['ID', grouper, 'CD'])['DATE'].agg([min, max]).droplevel(1)

输出:

min         max
ID  CD      
1   A   1/1/2015    1/4/2015
    B   1/5/2015    1/6/2015
    A   1/7/2015    1/8/2015
    C   1/9/2016    1/9/2016
2   A   1/2/2015    1/7/2015

更改列名并使用reset_index等来获得所需的输出

(df.groupby(['ID', grouper, 'CD'])['DATE'].agg([min, max]).droplevel(1)
 .set_axis(['Start_Date', 'End_Date'], axis=1)
 .reset_index()
 .assign(CD=lambda x: x.pop('CD')))

结果

ID  Start_Date  End_Date    CD
0   1   1/1/2015    1/4/2015    A
1   1   1/5/2015    1/6/2015    B
2   1   1/7/2015    1/8/2015    A
3   1   1/9/2016    1/9/2016    C
4   2   1/2/2015    1/7/2015    A

相关问题