【问题标题】:How to add rows based on a condition with another dataframe如何根据条件与另一个数据框添加行
【发布时间】:2021-06-29 19:04:14
【问题描述】:

我有两个数据框如下:

协议

  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

当付款数据框中的协议 ID 的总付款等于协议 ID 中的总费用时,我想在付款数据框中添加另一行。该行将在付款下包含零值,并且日期将计算为 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。

【问题讨论】:

  • 你能展示你尝试解决这个问题的代码吗?谢谢。
  • 您需要使用pd.to_datetime()date 转换为datetime 格式(请参阅doc)才能创建新的日期时间值——除非您想手动操作。跨度>
  • 我刚刚转换了。

标签: python python-3.x pandas numpy append


【解决方案1】:
import pandas as pd
import numpy as np

首先使用to_datetime()方法将支付数据框的'date'列转换为datetime dtype:

payments['date']=pd.to_datetime(payments['date'])

您可以使用groupby() 方法来做到这一点:

newdf=payments.groupby('agreement_id').agg({'payment':'sum','date':'min','cust_id':'first'}).reset_index()

现在通过布尔掩码获取满足您条件的数据:

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)

【讨论】:

  • 我在第 11 行和第 12 行有错字,因为我在付款项下输入了 150 而不是 0。无论如何,我只是将 result=pd.concat((payments,newdf),ignore_index=True).ffill() 替换为 result = pd.concat([payments,newdf], axis=0).fillna(0)
  • 哦...好的...在答案中更新了这个 :)
猜你喜欢
  • 1970-01-01
  • 2020-01-11
  • 2023-01-07
  • 2022-11-02
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
相关资源
最近更新 更多