首页 > 解决方案 > 计算重复(但唯一的记录)+ 连续记录

问题描述

我正在计算连续 + 重复日期(但唯一发票)的发票数量。我尝试将日期时间转换为字符串,然后计算序列,但它只计算每张发票的唯一日期。

# fix time format
df['Invoice Date'] = pd.to_datetime(df['Invoice Date'])

# column to find sequences
df = df.sort_values(['Vendor ID', 'Vendor Name', 'Invoice Date'])
df['continue'] = df['Invoice Date'].diff().dt.days.ne(1).cumsum()

# find time sequences
val_count = df['continue'].value_counts()
val_count = val_count[val_count.gt(1)].index.tolist()


#filter and group by Vendor
output = df[df['continue'].isin(val_count)].groupby(['Vendor ID'])['Vendor Name'].count()

电流输入:

供应商编号 供应商名称 发票日期 发票号码
8555 梅西百货 2020 年 1 月 1 日 1
8555 梅西百货 2020 年 1 月 2 日 2
8555 梅西百货 2020 年 1 月 3 日 3
8555 梅西百货 2020 年 1 月 3 日 4
8555 梅西百货 2020 年 1 月 3 日 5
8555 梅西百货 2020 年 1 月 5 日 6
1044 JC便士 2020 年 2 月 2 日 7
1044 JC便士 2020 年 2 月 3 日 8
1044 JC便士 2020 年 2 月 3 日 9
1044 JC便士 2020 年 2 月 8 日 10
1044 JC便士 2020 年 2 月 8 日 11

预期输出:

供应商编号 供应商名称 连续发票计数
8555 梅西百货 5
1044 JC便士 5

**8 月 24 日:**我正在编辑我的输入和预期输出。每个人都建议的代码是在我给出的前面的例子上工作,但不是在我的实际数据上。添加到它上面,以便它反映我遇到的问题。我已经使用了所有代码建议,但没有任何东西给 Macys 5、JC Penny 5。

**8 月 25 日:**使用当前代码(在 @Corralien 的帮助下)和数据框添加一个新示例

d = {'Vendor ID':
         {0: 8555, 1: 8555, 2: 8555, 3: 8555, 4: 8555, 5: 8555, 6: 8555,7: 8555, 8: 8555,9: 8555, 10: 8555, 11: 8555, 12: 8555, 13: 8555,
                   14: 1044, 15: 1044, 16: 1044, 17: 1044, 18: 1044, 19: 1044, 20: 1044, 21: 1044},
 'Vendor Name':
         {0: 'Macys', 1: 'Macys', 2: 'Macys', 3: 'Macys', 4: 'Macys',5: 'Macys', 6: 'Macys', 7: 'Macys', 8: 'Macys', 9: 'Macys', 10: 'Macys', 11: 'Macys', 12: 'Macys', 13: 'Macys',
                  14: 'JC Penny', 15: 'JC Penny', 16: 'JC Penny', 17: 'JC Penny', 18: 'JC Penny', 19: 'JC Penny', 20: 'JC Penny',21: 'JC Penny'},
 'Invoice Date':
         {0: '7/31/2020', 1: '7/31/2020', 2: '7/31/2020', 3: '7/31/2020', 4: '7/31/2020', 5: '2/14/2020', 6: '12/31/2019',7: '12/23/2019', 8: '7/14/2020', 9: '6/30/2020' , 10: '6/30/2020',
                  11: '6/30/2020',  12: '6/30/2020', 13: '6/30/2020', 14: '3/30/2020', 15: '3/20/2020', 16: '3/20/2020', 17: '3/20/2020', 18: '3/20/2020', 19: '2/27/2020', 20: '2/26/2020', 21: '2/26/2020'},
 'Invoice Number':
         {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7}}

df = pd.DataFrame(d)

# fix time format
df['Invoice Date'] = pd.to_datetime(df['Invoice Date'])

def count_consecutive_invoice(sr):
    # Find days that are less than or equal to 1 day (m1)
    m1 = sr.diff().le(pd.Timedelta(days=1))
    #  find first days of consecutive days (which is False in m1)
    m2 = (m1.eq(False) & m1.shift(-1).eq(True))
    return m1.sum() + m2.sum()

output = df.groupby(['Vendor ID', 'Vendor Name'])['Invoice Date'] \
      .apply(count_consecutive_invoice) \
      .rename('Count of Consecutive Invoices') \
      .reset_index()

电流输出:

   Vendor ID Vendor Name  Count of Consecutive Invoices
0       1044    JC Penny                              8
1       8555       Macys                             14

预期产出

   Vendor ID Vendor Name  Count of Consecutive Invoices
0       1044    JC Penny                              7
1       8555       Macys                             10

标签: pythonpandas

解决方案


对于每个组:

  • m1: 查找天数小于或等于 1 天 (m1)
  • m2: 查找连续天数的第一天(在 m1 中为 False)

然后总结2个系列。

def count_consecutive_invoice(sr):
    m1 = sr.sort_values().diff().le(pd.Timedelta(days=1))
    m2 = (m1.eq(False) & m1.shift(-1).eq(True))
    return m1.sum() + m2.sum()
# Ensure your 'Invoice Date' column is datetime64
# df['date'] = pd.to_datetime(df['date'])

>>> df.groupby(['Vendor ID', 'Vendor Name'])['Invoice Date'] \
      .apply(count_consecutive_invoice) \
      .rename('Count of Consecutive Invoices') \
      .reset_index()

   Vendor ID Vendor Name  Count of Consecutive Invoices
0       1044    JC Penny                              5
1       8555       Macys                              5

在您的真实数据上,现在的输出是:

   Vendor ID Vendor Name  Count of Consecutive Invoices
0       1044    JC Penny                              7
1       8555       Macys                             10

推荐阅读