如何解决在列和行级别的熊猫数据帧上应用两个lambda函数
我想根据 key_col 列表 groupby 一个熊猫数据框,并在每个组中执行两项操作:
- 首先根据 from_date_col 对值进行排序
- 对 to_date_col 列执行一次转换,并进行比较,该比较返回一个布尔值,并说明日期是否重叠或不重叠(请参见下面的测试示例)
我当前的代码如下:
def get_overlapping_date_range(df,key_col,from_date_col,to_date_col):
df['is_overlap'] = (df
.groupby(key_col)
.apply(lambda x: x.sort_values(from_date_col))
.apply(lambda x: (x[to_date_col].shift() - x[from_date_col]) > timedelta(0))
.reset_index(level=0,drop=True))
return df
这些lambda分别工作,但不能一起工作。我得到的错误是:KeyError: ('to','occurred at index id')
为了清楚起见,我想输入以下内容:
df = pd.DataFrame(columns=['id','from','to'],index=range(7),data=[[878,date(2006,1,1),date(2007,10,1)],[878,2),date(2008,12,date(2010,4,3)],[879,4),date(2199,5,10)],date(2016,12),31)],[880,date(2011,7,8),date(2013,3,2,date(2015,5)]])
并调用get_overlapping_date_range(df,'id','to')
并获得以下输出:
id from to is_overlap
0 878 2006-01-01 2007-10-01 False
1 878 2007-10-02 2008-12-01 False
2 878 2008-12-02 2010-04-03 False
3 879 2010-04-04 2199-05-10 False
4 879 2016-05-12 2199-12-31 True
5 880 2011-07-08 2013-03-03 False
6 880 2010-02-12 2015-05-05 True
我要在groupby中进行排序的原因是数据帧太大。 当col和row混合操作时,如何在groupby上应用两个lambda?我发现的所有solutions都是基于列的活动。
解决方法
from datetime import datetime
import pandas as pd
df = pd.DataFrame(columns=['id','from','to'],index=range(7),data=[[878,datetime(2006,1,1),datetime(2007,10,1)],[878,2),datetime(2008,12,datetime(2010,4,3)],[879,4),datetime(2199,5,10)],datetime(2016,12),31)],[880,datetime(2011,7,8),datetime(2013,3,2,datetime(2015,5)]])
print(df)
id from to
0 878 2006-01-01 2007-10-01
1 878 2007-10-02 2008-12-01
2 878 2008-12-02 2010-04-03
3 879 2010-04-04 2199-05-10
4 879 2016-05-12 2199-12-31
5 880 2011-07-08 2013-03-03
6 880 2010-02-12 2015-05-05
def check_date_by_id(df):
df['prevFrom'] = df['from'].shift()
df['prevTo'] = df['to'].shift()
def check_date_by_row(x):
if pd.isnull(x.prevFrom) or pd.isnull(x.prevTo):
x['overlap'] = False
return x
latest_start = max(x['from'],x.prevFrom)
earliest_end = min(x['to'],x.prevTo)
x['overlap'] = int((earliest_end - latest_start).days) + 1 > 0
return x
return df.apply(check_date_by_row,axis=1).drop(['prevFrom','prevTo'],axis=1)
print(df.groupby('id').apply(check_date_by_id))
id from to overlap
0 878 2006-01-01 2007-10-01 False
1 878 2007-10-02 2008-12-01 False
2 878 2008-12-02 2010-04-03 False
3 879 2010-04-04 2199-05-10 False
4 879 2016-05-12 2199-12-31 True
5 880 2011-07-08 2013-03-03 False
6 880 2010-02-12 2015-05-05 True
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。