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