与熊猫合并一些数据

时间:2018-08-21 15:40:27

标签: python pandas merge

我有一些这样的数据:

df = pd.DataFrame ({'code': ['A', 'A','A' ,'B', 'B','B', 'C'],
                     'type' : ['a', 'a', 'b', 'c', 'c', 'c', 'd'],
                     'start': ['2017-1-1', '2018-5-5', '2017-5-21', '2017-6-6','2017-7-8','2017-8-9','2018-5-1'],
                    'end': ['2017-5-20', 'now', '2017-5-4', '2017-7-7','2017-8-8','now','now']})

╔═══╦══════╦══════╦═══════════╦═══════════╗
║   ║ code ║ type ║ start     ║ end       ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 0 ║ A    ║ a    ║ 2017-1-1  ║ 2017-5-20 ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 1 ║ A    ║ a    ║ 2018-5-5  ║ now       ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 2 ║ A    ║ b    ║ 2017-5-21 ║ 2017-5-4  ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 3 ║ B    ║ c    ║ 2017-6-6  ║ 2017-7-7  ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 4 ║ B    ║ c    ║ 2017-7-8  ║ 2017-8-8  ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 5 ║ B    ║ c    ║ 2017-8-9  ║ now       ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 6 ║ C    ║ d    ║ 2018-5-1  ║ now       ║
╚═══╩══════╩══════╩═══════════╩═══════════╝

并且我想使用熊猫将其转换如下所示:

╔═══╦══════╦══════╦═══════════╦═══════════╗
║   ║ code ║ type ║ start     ║ end       ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 0 ║ A    ║ a    ║ 2017-1-1  ║ 2017-5-20 ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 1 ║ A    ║ a    ║ 2018-5-5  ║ now       ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 2 ║ A    ║ b    ║ 2017-5-21 ║ 2017-5-4  ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 3 ║ B    ║ c    ║ 2017-6-6  ║ now       ║
╠═══╬══════╬══════╬═══════════╬═══════════╣
║ 4 ║ C    ║ d    ║ 2018-5-1  ║ now       ║
╚═══╩══════╩══════╩═══════════╩═══════════╝

数据需要合并在 code type 字段中,这些字段的 date 值构成一个连续的日期范围(例如日期[ 2017-6-6],[2017-7-7],[2017-7-8],[2017-8-8],[2017-8-9],现在可以合并到[2017-6-6]改为 now )。

如果日期不连续,则不应将它们分组/合并,并且开始和结束均不得更改。 我该如何实现?

1 个答案:

答案 0 :(得分:1)

尝试一下:

grp_helper = df.groupby(['code','type'])\
               .apply(lambda x: (pd.to_datetime(x['start']) - 
                                 pd.to_datetime(x['end'], errors='coerce').shift(1) 
                                 != pd.Timedelta(days=1)).cumsum()).values

df.groupby(['code','type',grp_helper])[['start','end']]\
  .agg({'start':'min','end':'max'}).reset_index().drop('level_2', axis=1)

输出:

  code type      start        end
0    A    a   2017-1-1  2017-5-20
1    A    a   2018-5-5        now
2    A    b  2017-5-21   2017-5-4
3    B    c   2017-6-6        now
4    C    d   2018-5-1        now