如何根据另一个数据框的条件添加行
How to add rows based on a condition with another dataframe
我有两个数据框如下:
同意
agreement_id activation term_months total_fee
0 A 2020-12-01 24 4800
1 B 2021-01-02 6 300
2 C 2021-01-21 6 600
3 D 2021-03-04 6 300
付款
cust_id agreement_id date payment
0 1 A 2020-12-01 200
1 1 A 2021-02-02 200
2 1 A 2021-02-03 100
3 1 A 2021-05-01 200
4 1 B 2021-01-02 50
5 1 B 2021-01-09 20
6 1 B 2021-03-01 80
7 1 B 2021-04-23 90
8 2 C 2021-01-21 600
9 3 D 2021-03-04 150
10 3 D 2021-05-03 150
当支付数据框中 agreement_id 的总支付等于 agreement_id 中的 total_fee 时,我想在支付数据框中添加另一行。该行将包含付款下的零值,日期将计算为 min(date)(来自付款)加上 term_months(来自协议)。
这是我想要的支付数据框的结果:
付款
cust_id agreement_id date payment
0 1 A 2020-12-01 200
1 1 A 2021-02-02 200
2 1 A 2021-02-03 100
3 1 A 2021-05-01 200
4 1 B 2021-01-02 50
5 1 B 2021-01-09 20
6 1 B 2021-03-01 80
7 1 B 2021-04-23 90
8 2 C 2021-01-21 600
9 3 D 2021-03-04 150
10 3 D 2021-05-03 150
11 2 C 2021-07-21 0
12 3 D 2021-09-04 0
附加行是第 11 行和第 12 行。agreement_id 'C' 和 'D' 等于协议数据框中显示的 total_fee。
import pandas as pd
import numpy as np
首先使用to_datetime()
方法将付款数据框的'date'列转换为日期时间数据类型:
payments['date']=pd.to_datetime(payments['date'])
您可以使用 groupby()
方法来完成此操作:
newdf=payments.groupby('agreement_id').agg({'payment':'sum','date':'min','cust_id':'first'}).reset_index()
现在通过boolean masking得到满足你条件的数据:
newdf=newdf[agreement['total_fee']==newdf['payment']].assign(payment=np.nan)
注意: 在上面的代码中,我们使用了 assign()
方法并将付款行设为 NaN
现在使用pd.tseries.offsets.Dateoffsets()
方法和apply()
方法:
newdf['date']=newdf['date']+agreement['term_months'].apply(lambda x:pd.tseries.offsets.DateOffset(months=x))
注意:上面的代码给了你一个警告,所以忽略那个警告,因为它是警告而不是错误
最后利用concat()
方法和fillna()
方法:
result=pd.concat((payments,newdf),ignore_index=True).fillna(0)
现在如果你打印 result
你会得到你想要的输出
#output
cust_id agreement_id date payment
0 1 A 2020-12-01 200.0
1 1 A 2021-02-02 200.0
2 1 A 2021-02-03 100.0
3 1 A 2021-05-01 200.0
4 1 B 2021-01-02 50.0
5 1 B 2021-01-09 20.0
6 1 B 2021-03-01 80.0
7 1 B 2021-04-23 90.0
8 2 C 2021-01-21 600.0
9 3 D 2021-03-04 150.0
10 3 D 2021-05-03 150.0
11 2 C 2021-07-21 0.0
12 3 D 2021-09-04 0.0
注意: 如果您想要完全相同的输出,请使用 astype()
方法并将付款列 dtype 从 float
更改为 int
result['payment']=result['payment'].astype(int)
我有两个数据框如下:
同意
agreement_id activation term_months total_fee
0 A 2020-12-01 24 4800
1 B 2021-01-02 6 300
2 C 2021-01-21 6 600
3 D 2021-03-04 6 300
付款
cust_id agreement_id date payment
0 1 A 2020-12-01 200
1 1 A 2021-02-02 200
2 1 A 2021-02-03 100
3 1 A 2021-05-01 200
4 1 B 2021-01-02 50
5 1 B 2021-01-09 20
6 1 B 2021-03-01 80
7 1 B 2021-04-23 90
8 2 C 2021-01-21 600
9 3 D 2021-03-04 150
10 3 D 2021-05-03 150
当支付数据框中 agreement_id 的总支付等于 agreement_id 中的 total_fee 时,我想在支付数据框中添加另一行。该行将包含付款下的零值,日期将计算为 min(date)(来自付款)加上 term_months(来自协议)。
这是我想要的支付数据框的结果:
付款
cust_id agreement_id date payment
0 1 A 2020-12-01 200
1 1 A 2021-02-02 200
2 1 A 2021-02-03 100
3 1 A 2021-05-01 200
4 1 B 2021-01-02 50
5 1 B 2021-01-09 20
6 1 B 2021-03-01 80
7 1 B 2021-04-23 90
8 2 C 2021-01-21 600
9 3 D 2021-03-04 150
10 3 D 2021-05-03 150
11 2 C 2021-07-21 0
12 3 D 2021-09-04 0
附加行是第 11 行和第 12 行。agreement_id 'C' 和 'D' 等于协议数据框中显示的 total_fee。
import pandas as pd
import numpy as np
首先使用to_datetime()
方法将付款数据框的'date'列转换为日期时间数据类型:
payments['date']=pd.to_datetime(payments['date'])
您可以使用 groupby()
方法来完成此操作:
newdf=payments.groupby('agreement_id').agg({'payment':'sum','date':'min','cust_id':'first'}).reset_index()
现在通过boolean masking得到满足你条件的数据:
newdf=newdf[agreement['total_fee']==newdf['payment']].assign(payment=np.nan)
注意: 在上面的代码中,我们使用了 assign()
方法并将付款行设为 NaN
现在使用pd.tseries.offsets.Dateoffsets()
方法和apply()
方法:
newdf['date']=newdf['date']+agreement['term_months'].apply(lambda x:pd.tseries.offsets.DateOffset(months=x))
注意:上面的代码给了你一个警告,所以忽略那个警告,因为它是警告而不是错误
最后利用concat()
方法和fillna()
方法:
result=pd.concat((payments,newdf),ignore_index=True).fillna(0)
现在如果你打印 result
你会得到你想要的输出
#output
cust_id agreement_id date payment
0 1 A 2020-12-01 200.0
1 1 A 2021-02-02 200.0
2 1 A 2021-02-03 100.0
3 1 A 2021-05-01 200.0
4 1 B 2021-01-02 50.0
5 1 B 2021-01-09 20.0
6 1 B 2021-03-01 80.0
7 1 B 2021-04-23 90.0
8 2 C 2021-01-21 600.0
9 3 D 2021-03-04 150.0
10 3 D 2021-05-03 150.0
11 2 C 2021-07-21 0.0
12 3 D 2021-09-04 0.0
注意: 如果您想要完全相同的输出,请使用 astype()
方法并将付款列 dtype 从 float
更改为 int
result['payment']=result['payment'].astype(int)