我的数据包括发票,我必须检查发票是否已经付款。
对于每个发票,我循环查看所有报告日期如果在某一天,发票没有出现,这意味着客户已经支付了款项,当然在随后的日子里也不会再出现。
从下表可以看出,发票C是在2005年28月支付的。

Report Date  Invoice No
2019-05-28   D
2019-05-28   A
2019-05-28   B

2019-05-27   A
2019-05-27   B
2019-05-27   C

2019-05-26   A
2019-05-26   B
2019-05-26   C

我写了下面的代码,它工作了,但是花费了太长的时间,因为有大约800k个条目。这是非常低效的。我想知道是否有一个更有效的方法来解决这个问题使用熊猫。
# For every Invoice
for i in range(0,len(documentNo.categories)):
    # If the invoice still exists in the newest Report Date (here 28/05), means that it has not been paid yet. So we can skip to check other invoices
    if (df.loc[(df['Document No'] == documentNo.categories[i]) & (df['Report Date'] == reportDates.categories[len(reportDates.categories) - 1])].all(1).any()):
        continue

    # Decrement from date 27/05
    for j in range(len(reportDates.categories) - 2,0,-1):

        # If the Invoice does not exist on this date, it has been paid
        if (df.loc[(df['Document No'] == documentNo.categories[i]) & (df['Report Date'] != reportDates.categories[j])].all(1).any()):
            break

因此,我需要一个新列,显示每行的打开/关闭。
Report Date  Invoice No  Open/Closed
2019-05-28   D           Open
2019-05-28   A           Open
2019-05-28   B           Open

2019-05-27   A           Open
2019-05-27   B           Open
2019-05-27   C           Closed

2019-05-26   A           Open
2019-05-26   B           Open
2019-05-26   C           Closed

最佳答案

下面是我们使用crosstab的方法,然后是发票eq为0,这意味着以前的发票应计为Closed

s=pd.crosstab(df.ReportDate,df.InvoiceNo).eq(0)

Newdf=(s.iloc[::-1,:].cummax()&~s).replace({True:'Closed',False:'Open'}).stack().reindex(pd.MultiIndex.from_frame(df)).reset_index()
Newdf
Out[342]:
   ReportDate InvoiceNo       0
0  2019-05-28         D    Open
1  2019-05-28         A    Open
2  2019-05-28         B    Open
3  2019-05-27         A    Open
4  2019-05-27         B    Open
5  2019-05-27         C  Closed
6  2019-05-26         A    Open
7  2019-05-26         B    Open
8  2019-05-26         C  Closed

09-25 20:55