对于一列中给定的日期,另一列中有多少日期小于该日期?

2024-05-12 19:00:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我有下表:

id | invoice_date | payment_date
--------------------------------
1  | 2017-03-01   | 2017-03-03
1  | 2017-03-04   | 2017-03-06
1  | 2017-03-04   | 2017-03-11
1  | 2017-03-15   | 2017-03-16
1  | 2017-03-21   | 2017-03-31
2  | 2017-01-22   | 2017-01-22
2  | 2017-01-24   | 2017-01-25

我想知道:对于表中的任何给定索引,有多少索引较小的付款日期小于索引的发票日期?也就是说,对于一个给定的发票日期,有多少个付款日期提前?理想情况下,我希望为每个id(按分组)执行此操作,因此我有如下内容:

id | invoice_date | payment_date | num_pay_dates_less_than_inv_date
------------------------------------------------------------------
1  | 2017-03-01   | 2017-03-03   | 0
1  | 2017-03-04   | 2017-03-06   | 1
1  | 2017-03-04   | 2017-03-11   | 1
1  | 2017-03-15   | 2017-03-16   | 3
1  | 2017-03-21   | 2017-03-31   | 4
2  | 2017-01-22   | 2017-01-22   | 0
2  | 2017-01-24   | 2017-01-25   | 1

Tags: id内容date情况发票invoicepaymentpay
2条回答

我能够使用@COLDSPEEDs推荐的方法来编写一个循环,给出他/她的答案。在大小为50K的数据帧上,循环实现的执行速度比非循环实现快20倍。数据帧的列是id、value1和value2

def f(grp):

    dxv = {}
    for ix, val in zip(grp.index, grp.value1[:, None]):
        if (val > grp.value2.values[:ix]).any():
            dxv[ix] = (val > grp.value2.values[:ix]).cumsum()[-1]
        else:
            dxv[ix] = 0
    return pd.Series(dxv)

这对于我的案例非常有效,使用:

df['num_pay_dates_less_than_inv_date'] = \
df.groupby(['id']).apply(f).reset_index(drop=True)

请随意进一步优化

Numpy解决方案。使用广播比较,然后沿第一个轴执行cumsum操作。最后,提取对角线元素并赋给df

v = (df.invoice_date[:, None] > df.payment_date.values).cumsum(1)
df['num_pay_dates_less_than_inv_date'] = v[np.diag_indices_from(v)]

df

   id invoice_date payment_date  num_pay_dates_less_than_inv_date
0   1   2017-03-01   2017-03-03                                 0
1   1   2017-03-04   2017-03-06                                 1
2   1   2017-03-04   2017-03-11                                 1
3   1   2017-03-15   2017-03-16                                 3
4   1   2017-03-21   2017-03-31                                 4
5   2   2017-01-22   2017-01-22                                 0
6   2   2017-01-24   2017-01-25                                 1

这要求两个列都采用datetime格式(否则,比较是按字典顺序进行的,这通常是可以的,但此时将取决于您的日期格式)

相关问题 更多 >