【问题标题】:Calculating aged tickets open at a given point in time计算在给定时间点打开的旧票
【发布时间】:2020-04-23 21:10:55
【问题描述】:

背景: 我们有一个票务系统,每张票都有开放日期、关闭日期、类别、类型等字段。每张票在我的数据中由一行表示,并带有一个用于识别票的键。

单个记录可能如下所示:

Number, Type, Category, Opened, Closed
TICKET100, Database, Software, 2/1/2020 11:30 AM, 4/22/2020 4:40 PM

目标: 我的目标是创建一个函数,该函数采用输入数据框(熊猫)、某种类型的输入年龄参数和属性/维度列表。然后,该函数将返回一个数据框,其中包含基于该年龄参数、每个属性/维度、日期的特定年龄之后打开的票证数量。

输入示例:

ticket_age(input_dataframe, age=5, dimensions=['Type','Category'])

所需输出的示例 sn-p:

Date, Type, Category, Count
3/1/2020, Database, Software, 1
3/2/2020, Database, Software, 1
...
4/22/2020, Database, Software, 0

关于输出的一个重要说明...如果日期和维度的交集没有任何满足条件的票,它应该创建一个计数为 0 的行。

我被困在哪里: 我不知道如何接受未知大小列表的维度并遍历所有这些维度。

我尝试了什么?当我通过维度对循环进行硬编码时,我已经成功生成了符合年龄标准的票数。

我如何计算 type_list、first_date 和 total_days:

    #Create function to find the minimum date
def date_minimum(input_dataframe, date_to_check):
    return input_dataframe[date_to_check].min().date()

#Create function to find the maximum date
def date_maximum(input_dataframe,date_to_check):
    return input_dataframe[date_to_check].max().date()

    #setup min and max dates
    min_date=date_minimum(df_aged_input,'Opened')
    max_date=date_maximum(df_aged_input,'Closed')
    #Get the first relevant date for the dataframe loop
    first_date=min_date+datetime.timedelta(days=aged_window)

    # Generate a list of unique assignment groups
    type_list=df_aged_input['Type'].unique().tolist()

我的循环

aged_output_list=[]
for type_iterate in range(len(type_list)):
    #filter by the type
    aged_type=type_list[type_iterate]
    df_aged_input=df_tkt_relevant[df_tkt_relevant['Type']==aged_type].copy()
    for date_iterate in range(totalDays.days):
        #generate the aged date iterator
        aged_date=first_date+datetime.timedelta(days=date_iterate)
        #Count the number of records in the data frame that match the input conditions
        aged_frame=df_aged_input[(~(df_aged_input['Closed'].dt.date<aged_date))&(df_aged_input['Opened'].dt.date<(aged_date-datetime.timedelta(days=aged_window+1)))].copy()
        aged_frame['aged_Date']=aged_date-datetime.timedelta(days=1)
        aged_count=aged_frame.shape[0]
        #Write the date from iterative date and the aged count to a new data source
        aged_output_list.append([aged_date,aged_type or 'Error: Missing Type',aged_count])

接下来我该怎么做?是否有其他图书馆可以为我完成所有这些工作?

【问题讨论】:

  • 这可以用pandas方法快速完成,你能解释一下age参数,年龄和日期之间的关系是什么? count 也是该特定日期数据框中的票数吗?
  • @ChrisG 有未定义的变量...我不知道first_datetotalDaystype_list 是什么。
  • @ChrisG 谢谢。开始有了更好的理解。我仍然不清楚的一件事是TotalDays 和预期的输出。预期输出中的日期似乎是任意的[3/1/2020, 3/2/2020, 4/22/2020] 你能提供更多关于预期输出的信息吗
  • @Yo_Chris:感谢您提出的好问题。我现在回想起来,我提供的日期相当随意。我添加了一个省略号,希望能建议两者之间的所有日期。从技术上讲,它应该是(包括)“第一个日期”和“最大日期”之间的所有天
  • @ChrisG 完美,我现在明白了。再问一个问题,能不能多行同一个Number['ticket100', 'ticket101', 'ticket100']

标签: python python-3.x pandas


【解决方案1】:

IIUC

import pandas as pd
from pandas.tseries.offsets import DateOffset
from io import StringIO
import numpy as np

# sample data
s = """Number,Type,Category,Opened,Closed
TICKET100,Database,Software,2/1/2020 11:30 AM,2/22/2020 4:40 PM
TICKET101,Database,Software,2/10/2020 11:30 AM,2/23/2020 4:40 PM
TICKET102,Database,Software,2/11/2020 11:30 AM,2/22/2020 4:40 PM
TICKET103,something,else,2/10/2020 11:30 AM,2/23/2020 4:40 PM
TICKET104,something,else,2/12/2020 11:30 AM,2/22/2020 4:40 PM"""
df = pd.read_csv(StringIO(s))

# convert to datetime
df['Opened'] = pd.to_datetime(df['Opened'])
df['Closed'] = pd.to_datetime(df['Closed'])

# create a function
def myFunc(df, age, dimensions):
    # zip the date offset for open and close together
    z = zip(df['Opened'].dt.date + DateOffset(age), df['Closed'].dt.date - DateOffset(age))
    # create a daterange for each record in the dataframe
    df['date_range'] = [pd.date_range(o, c, freq='D') for o,c in z]
    # groupby your dimensions columns
    g = df.groupby(dimensions)
    # list comprehension for each group and create the date range
    idxs = [pd.date_range(df['Opened'].min(), df['Closed'].max(), freq='D',
                          normalize=True) for _,df in g]
    # sum all the true values where the datetime index create above
    # is in the date_range column
    l = [[sum(df[1]['date_range'].apply(lambda x: idx.isin(x))),
          idx, [df[0]]*len(idx)] for idx,df  in zip(idxs, g)]
    # transpose and hstack the list
    arr = np.transpose(np.hstack(l))
    # return pandas dataframe
    return pd.DataFrame(arr, columns=['count', 'date', 'dimensions'])

out = myFunc(df, 5, ['Type', 'Category'])

    count       date             dimensions
0       0 2020-02-01  (Database, Software)
1       0 2020-02-02  (Database, Software)
2       0 2020-02-03  (Database, Software)
3       0 2020-02-04  (Database, Software)
4       0 2020-02-05  (Database, Software)
5       1 2020-02-06  (Database, Software)
6       1 2020-02-07  (Database, Software)
7       1 2020-02-08  (Database, Software)
8       1 2020-02-09  (Database, Software)
9       1 2020-02-10  (Database, Software)
10      1 2020-02-11  (Database, Software)
11      1 2020-02-12  (Database, Software)
12      1 2020-02-13  (Database, Software)
13      1 2020-02-14  (Database, Software)
14      2 2020-02-15  (Database, Software)
15      3 2020-02-16  (Database, Software)
16      3 2020-02-17  (Database, Software)
17      1 2020-02-18  (Database, Software)
18      0 2020-02-19  (Database, Software)
19      0 2020-02-20  (Database, Software)
20      0 2020-02-21  (Database, Software)
21      0 2020-02-22  (Database, Software)
22      0 2020-02-23  (Database, Software)
23      0 2020-02-10     (something, else)
24      0 2020-02-11     (something, else)
25      0 2020-02-12     (something, else)
26      0 2020-02-13     (something, else)
27      0 2020-02-14     (something, else)
28      1 2020-02-15     (something, else)
29      1 2020-02-16     (something, else)
30      2 2020-02-17     (something, else)
31      1 2020-02-18     (something, else)
32      0 2020-02-19     (something, else)
33      0 2020-02-20     (something, else)
34      0 2020-02-21     (something, else)
35      0 2020-02-22     (something, else)
36      0 2020-02-23     (something, else)

【讨论】:

  • 感谢 Yo_Chris 的回答。我会在接下来的 24 小时内验证并回复。
  • @ChrisG,没问题,如果您遇到任何问题,请告诉我。另外,回顾您的问题,我可能已经在z = zip(...) 中编造了关于df['Closed'] - DateOffset(age) 的部分您可能需要为df['Closed'] 删除DateOffset,因为现在票必须至少在@ 987654326@ 设置为,并且工单必须有一个关闭日期减去年龄。这就是为什么索引 18-22 和索引 32-36 的计数为 0
  • 谢谢你 yo_chris,我仍在进行重构,无法确认赞成/反对...但你应该得到赏金,因为你试图提供帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
相关资源
最近更新 更多