通过groupby建立开始/结束日期

时间:2015-11-26 13:22:18

标签: python pandas dataframe

我正在尝试找到一个很好的干净的Python / Pandas方法来获取以下数据帧:

ID  Date_Field Category 
12345 01/01/12 AAAA
12345 01/02/12 AAAA
12345 01/03/12 AAAA
12345 01/04/12 BBBB
12345 01/05/12 BBBB
12345 01/06/12 BBBB
2468  01/01/12 AAAA
2468  01/02/12 AAAA
2468  01/03/12 AAAA
2468  01/04/12 BBBB
2468  01/05/12 BBBB
2468  01/06/12 BBBB
2468  01/07/12 BBBB
2468  01/08/12 CCCC
2468  01/09/12 CCCC
2468  01/10/12 AAAA
2468  01/11/12 AAAA

并将其转换为与此类似的数据框,即我有每个ID /类别的开始/结束日期,但有一点需要注意,如果日期之间存在日期差异,ID /类别组合可能会多次出现:

ID  Start_Date End_Date Category
12345 01/01/12 01/03/12 AAAA
12345 01/04/12 01/06/12 BBBB
2468  01/01/12 01/03/12 AAAA
2468  01/10/12 01/11/12 AAAA
2468  01/04/12 01/07/12 BBBB
2468  01/08/12 01/09/12 CCCC

我知道我可以通过迭代和比较之前的行值来做到这一点,但我感觉有一个更清晰的方法。

1 个答案:

答案 0 :(得分:3)

你可以groupby。如果您只想要一个列,则可以执行以下操作:

>>> df.groupby(['ID','Category']).min()

               Date_Field
ID    Category           
2468  AAAA       01/01/12
      BBBB       01/04/12
      CCCC       01/08/12
12345 AAAA       01/01/12
      BBBB       01/04/12

并且你也可以做this answer

>>> df.groupby(['ID','Category']).agg({'Date_Field' : [min, max]})

               Date_Field          
                      min       max
ID    Category                     
2468  AAAA       01/01/12  01/11/12
      BBBB       01/04/12  01/07/12
      CCCC       01/08/12  01/09/12
12345 AAAA       01/01/12  01/03/12
      BBBB       01/04/12  01/06/12


修改

groupby会产生DataFramegrouped columns as index,以禁用此添加as_index=False

>>> df.groupby(['ID','Category'], as_index=False).agg({'Date_Field' : [min, max]})

      ID Category Date_Field          
                         min       max
0   2468     AAAA   01/01/12  01/11/12
1   2468     BBBB   01/04/12  01/07/12
2   2468     CCCC   01/08/12  01/09/12
3  12345     AAAA   01/01/12  01/03/12
4  12345     BBBB   01/04/12  01/06/12


编辑2

要使用相同的ID和类别分隔数据的不同时间间隔,我们必须添加新类别:

df['Cat2']=0
for i in range(2,len(df)):
   if df['Category'].iloc[i]==df['Category'][i-1]:
     df['Cat2'].iloc[i]=df['Cat2'].iloc[i-1]
   else:
     df['Cat2'].iloc[i]=df['Cat2'].iloc[i-1]+1

这个for循环创建一个新的Cat2列,如果前一行(i-1)具有相同的Category,它将具有相同的值,否则将创建一个新值(前一个+ 1) )。请注意,此方法完全取决于数据的顺序! 现在我们可以将其添加到groupby类别:

 >>> df.groupby(['ID','Category','Cat2'], as_index=False).agg({'Date_Field' : [min, max]})

      ID Category Cat2 Date_Field          
                              min       max
0   2468     AAAA    2   01/01/12  01/03/12
1   2468     AAAA    5   01/10/12  01/11/12
2   2468     BBBB    3   01/04/12  01/07/12
3   2468     CCCC    4   01/08/12  01/09/12
4  12345     AAAA    0   01/01/12  01/03/12
5  12345     BBBB    1   01/04/12  01/06/12