gpt4 book ai didi

python - 在 Pandas Dataframe 中组合日期范围

转载 作者:太空宇宙 更新时间:2023-11-04 02:49:43 26 4
gpt4 key购买 nike

我在 Python 中有一组记录,其中包含一个 ID、至少一个属性和一组日期范围。我想要获取每个 id 的代码,并结合属性匹配且日期范围内没有间隙的所有记录。

日期范围内没有间隙,我的意思是一条记录的结束日期大于或等于该 ID 的下一条记录。

例如,ID 为“10”、开始日期为“2016-01-01”和结束日期为“2017-01-01”的记录可以与具有该 ID、开始日期为“2017-”的另一条记录合并01-01”,结束日期为“2018-01-01”,但不能与开始于“2017-01-10”的记录合并,因为与 2017-01- 01 至 2017-01-09.

这里有一些例子——

有:

FruitID,FruitType,StartDate,EndDate
1,Apple,2015-01-01,2016-01-01
1,Apple,2016-01-01,2017-01-01
1,Apple,2017-01-01,2018-01-01
2,Orange,2015-01-01,2016-01-01
2,Orange,2016-05-31,2017-01-01
2,Orange,2017-01-01,2018-01-01
3,Banana,2015-01-01,2016-01-01
3,Banana,2016-01-01,2017-01-01
3,Blueberry,2017-01-01,2018-01-01
4,Mango,2015-01-01,2016-01-01
4,Kiwi,2016-09-15,2017-01-01
4,Mango,2017-01-01,2018-01-01

想要:

FruitID,FruitType,NewStartDate,NewEndDate
1,Apple,2015-01-01,2018-01-01
2,Orange,2015-01-01,2016-01-01
2,Orange,2016-05-31,2018-01-01
3,Banana,2015-01-01,2017-01-01
3,Blueberry,2017-01-01,2018-01-01
4,Mango,2015-01-01,2016-01-01
4,Kiwi,2016-09-15,2017-01-01
4,Mango,2017-01-01,2018-01-01

我目前的解决方案如下。它提供了我正在寻找的结果,但对于大型数据集来说性能似乎不太好。此外,我的印象是您通常希望尽可能避免迭代数据框的各个行。非常感谢您提供的任何帮助!

import pandas as pd
from dateutil.parser import parse

have = pd.DataFrame.from_items([('FruitID', [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]),
('FruitType', ['Apple', 'Apple', 'Apple', 'Orange', 'Orange', 'Orange', 'Banana', 'Banana', 'Blueberry', 'Mango', 'Kiwi', 'Mango']),
('StartDate', [parse(x) for x in ['2015-01-01', '2016-01-01', '2017-01-01', '2015-01-01', '2016-05-31',
'2017-01-01', '2015-01-01', '2016-01-01', '2017-01-01', '2015-01-01', '2016-09-15', '2017-01-01']]),
('EndDate', [parse(x) for x in ['2016-01-01', '2017-01-01', '2018-01-01', '2016-01-01', '2017-01-01',
'2018-01-01', '2016-01-01', '2017-01-01', '2018-01-01', '2016-01-01', '2017-01-01', '2018-01-01']])
])

have.sort_values(['FruitID', 'StartDate'])

rowlist = []
fruit_cur_row = None

for row in have.itertuples():
if fruit_cur_row is None:
fruit_cur_row = row._asdict()
fruit_cur_row.update(NewStartDate=row.StartDate, NewEndDate=row.EndDate)

elif not(fruit_cur_row.get('FruitType') == row.FruitType):
rowlist.append(fruit_cur_row)

fruit_cur_row = row._asdict()
fruit_cur_row.update(NewStartDate=row.StartDate, NewEndDate=row.EndDate)

elif (row.StartDate <= fruit_cur_row.get('NewEndDate')):
fruit_cur_row['NewEndDate'] = max(fruit_cur_row['NewEndDate'], row.EndDate)
else:
rowlist.append(fruit_cur_row)
fruit_cur_row = row._asdict()
fruit_cur_row.update(NewStartDate=row.StartDate, NewEndDate=row.EndDate)

rowlist.append(fruit_cur_row)
have_mrg = pd.DataFrame.from_dict(rowlist)
print(have_mrg[['FruitID', 'FruitType', 'NewStartDate', 'NewEndDate']])

最佳答案

使用嵌套的 groupby 方法:

def merge_dates(grp):
# Find contiguous date groups, and get the first/last start/end date for each group.
dt_groups = (grp['StartDate'] != grp['EndDate'].shift()).cumsum()
return grp.groupby(dt_groups).agg({'StartDate': 'first', 'EndDate': 'last'})

# Perform a groupby and apply the merge_dates function, followed by formatting.
df = df.groupby(['FruitID', 'FruitType']).apply(merge_dates)
df = df.reset_index().drop('level_2', axis=1)

请注意,此方法假定您的日期已经排序。如果没有,您需要先在 DataFrame 上使用 sort_values。如果您有嵌套的日期跨度,此方法可能不起作用。

结果输出:

   FruitID  FruitType   StartDate     EndDate
0 1 Apple 2015-01-01 2018-01-01
1 2 Orange 2015-01-01 2016-01-01
2 2 Orange 2016-05-31 2018-01-01
3 3 Banana 2015-01-01 2017-01-01
4 3 Blueberry 2017-01-01 2018-01-01
5 4 Kiwi 2016-09-15 2017-01-01
6 4 Mango 2015-01-01 2016-01-01
7 4 Mango 2017-01-01 2018-01-01

关于python - 在 Pandas Dataframe 中组合日期范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44267366/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com