python 我正在想办法计算两件事之间的天数

pxyaymoc  于 2023-05-16  发布在  Python
关注(0)|答案(5)|浏览(100)

我有一个事件列表。每个案例(案例ID)最终将经历事件(事件A、事件B)。我有包含相应事件的时间戳的列。我试图找到事件A和事件B之间的日子,基于下面使用Python。然而,有些情况下,通过事件一个以上的时间,我需要的时间间隔是基于最新的日期。在以下示例中,案例ID 1的最新日期为1/20/23,忽略此案例ID的事件A的前两次发生。
|案例ID|活动|日期|------------------|1|一个|1/1/23||1|一个|1/3/23||1|一个|1/20/23||1| B| 2/1/23||8|一个|1/2/23||100|一个|3/1/23||100| B| 3/2/23||35|一个|2/13/23||35| B| 2/27/23||6|一个|2/14/23||33|一个|2/26/23||2|一个|3/4/23||2| B| 4/30/23|
我尝试过按重复排序,但我使用Python不像使用SQL那样舒服,而且我无法使用SQL。还试图避免手动删除重复项。我期望的输出看起来像下面这样:|案例ID| busdaysbweventAB|

arknldoa

arknldoa1#

您可以用途:

# Convert to datetime64 if needed
df['DATE'] = pd.to_datetime(df['DATE'])

# Pandas part: reshape your dataframe
out = df.sort_values('DATE').pivot_table(index='CaseID', columns='EVENT', values='DATE', aggfunc='last')
m = out.notna().all(axis=1)

# Numpy part: compute business day
arr = out[m].values.astype('datetime64[D]')
out.loc[m, 'bdays'] = np.busday_count(arr[:, 0], arr[:, 1])

输出:

>>> out
EVENT           A          B  bdays
CaseID                             
1      2023-01-20 2023-02-01    8.0
2      2023-03-04 2023-04-30   40.0
6      2023-02-14        NaT    NaN
8      2023-01-02        NaT    NaN
33     2023-02-26        NaT    NaN
100    2023-03-01 2023-03-02    1.0
kx1ctssn

kx1ctssn2#

您的输入数据采用管道分隔的CSV文件的形式。它非常简单,因此不需要任何模块导入来处理它。
构建一个以CaseID为键的字典。每个关联的值都应该是一个字典,可以同时包含“A”和“B”键。日期应该在与这些键关联的列表中。
您需要解析日期以找到最大值(最近的),然后做一些算术运算。
给定输入文件foo.csv,其中包含以下内容:

|CaseID|EVENT|DATE|
|1|A|1/1/23|
|1|A|1/3/23|
|1|A|1/20/23|
|1|B|2/1/23|
|8|A|1/2/23|
|100|A|3/1/23|
|100|B|3/2/23|
|6|A|2/14/23|
|33|A|2/26/23|
|2|A|3/4/23|
|2|B|4/30/23|

代码可能看起来像这样:

from datetime import datetime

def parse(d):
    return datetime.strptime(d, '%m/%d/%y')

mydict = dict()

with open('foo.csv') as data:
    next(data) # skip column headers
    for line in data:
        _, case, event, date, *_ = line.split('|')
        _date = parse(date)
        if case in mydict:
            mydict[case].setdefault(event, []).append(_date)
        else:
            mydict[case] = {event: [_date]}

for k, v in mydict.items():
    if 'A' in v and 'B' in v:
        maxa = max(v['A'])
        maxb = max(v['B'])
        print('CaseID', k, abs((maxa-maxb).days))

输出:

CaseID 1 12
CaseID 100 1
CaseID 2 57
gpnt7bae

gpnt7bae3#

假设数据如所示(即caseID值和DATE排序-否则您可以在进一步处理之前排序),然后首先将CSV数据读入pandas DataFrame;然后用途:

#convert date strings to datetime format
df['DATE'] = pd.to_datetime(df['DATE'], dayfirst = False)
#drop duplicated A rows
df = df.drop_duplicates(subset = ['CaseID', 'EVENT'], keep = 'last')
#calculate difference of days
df['days'] = df.groupby('CaseID')['DATE'].diff().dt.days
#and finally lose the case without an A and a B event
df = df.dropna()

这导致:

CaseID EVENT       DATE  days
3        1     B 2023-02-01  12.0
6      100     B 2023-03-02   1.0
10       2     B 2023-04-30  57.0
goqiplq2

goqiplq24#

另一种方法是按事件和ID分组,获得最大日期,再次按ID分组,并使用apply获得日期之间的差异。

from io import StringIO

import pandas as pd

table = """
CaseID,EVENT,DATE
1,A,1/1/23
1,A,1/3/23
1,A,1/20/23
1,B,2/1/23
8,A,1/2/23
100,A,3/1/23
100,B,3/2/23
6,A,2/14/23
33,A,2/26/23
2,A,3/4/23
2,B,4/30/23
"""

df = pd.read_csv(StringIO(table), sep=',')
df['DATE'] = pd.to_datetime(df['DATE'])
d = df.groupby(['CaseID', 'EVENT']).max().reset_index().groupby('CaseID').aggregate({'DATE': lambda x: x.diff().to_numpy()[-1]})

输出:

DATE
CaseID        
1      12 days
2      57 days
6          NaT
8          NaT
33         NaT
100     1 days
uemypmqf

uemypmqf5#

案例ID活动日期
1一个23年1月1日
1一个23年1月3日
1一个1/20/23
1B23年2月1日
一个23年1月2日
一百一个23年3月1日
一百B23年3月2日
三十五一个23年2月13日
三十五B23年2月27日
一个23年2月14日
三十三一个23年2月26日
一个23年3月4日
B四月三十日二十三日
import pandas as pd

def get_time_lapsed(df, case_id, event, date):
    df = df.sort_values(by=[case_id, date])
    df["time_lapsed"] = df.groupby(case_id)[date].diff()
    return df
def test_get_time_lapsed():
    df = pd.DataFrame(
        {
            "CaseID": [1, 1, 1, 1, 8, 100, 100, 35, 35, 6, 33, 2, 2],
            "EVENT": ["A", "A", "A", "B", "A", "A", "B", "A", "B", "A", "A", "A", "B"],
            "DATE": [
                "1/1/23",
                "1/3/23",
                "1/20/23",
                "2/1/23",
                "1/2/23",
                "3/1/23",
                "3/2/23",
                "2/13/23",
                "2/27/23",
                "2/14/23",
                "2/26/23",
                "3/4/23",
                "4/30/23",
            ],
        }
    )
    df["DATE"] = pd.to_datetime(df["DATE"])
    df = get_time_lapsed(df, "CaseID", "EVENT", "DATE")
    print(df)
CaseID EVENT       DATE time_lapsed
0        1     A 2023-01-01         NaT
1        1     A 2023-01-03      2 days
2        1     A 2023-01-20     17 days
3        1     B 2023-02-01     12 days
11       2     A 2023-03-04         NaT
12       2     B 2023-04-30     57 days
9        6     A 2023-02-14         NaT
4        8     A 2023-01-02         NaT
10      33     A 2023-02-26         NaT
7       35     A 2023-02-13         NaT
8       35     B 2023-02-27     14 days
5      100     A 2023-03-01         NaT
6      100     B 2023-03-02      1 days

相关问题