Jak vypočítat rozdíl mezi v hodinách dvě časová razítka a vyloučit víkendech

0

Otázka

Mám datovém jako je tento:

     Folder1                   Folder2                 
0   2021-11-22 12:00:00      2021-11-24 10:00:00
1   2021-11-23 10:30:00      2021-11-25 18:30:00    
2   2021-11-12 10:30:00      2021-11-15 18:30:00    
3   2021-11-23 10:00:00            NaN         

         

Pomocí tohoto kódu:

def strfdelta(td: pd.Timestamp):
    seconds = td.total_seconds()
    hours = int(seconds // 3600)
    minutes = int((seconds % 3600) // 60)
    seconds = int(seconds % 60)
    return f"{hours:02}:{minutes:02}:{seconds:02}"
            
df["Folder1"] = pd.to_datetime(df["Folder1"])
df["Folder2"] = pd.to_datetime(df["Folder2"])

bm1 = df["Folder1"].notna() & df["Folder2"].notna()
bm2 = df["Folder1"].notna() & df["Folder2"].isna()

df["Time1"] = (df.loc[bm1, "Folder2"] - df.loc[bm1, "Folder1"]).apply(strfdelta)
df["Time2"] = (datetime.now() - df.loc[bm2, "Folder1"]).apply(strfdelta)

Mám df:

     Folder1                   Folder2                           Time1     Time2
0   2021-11-22 12:00:00      2021-11-24 10:00:00                46:00:00    NaN
1   2021-11-23 10:30:00      2021-11-25 18:30:00                56:00:00    NaN
2   2021-11-12 10:30:00      2021-11-15 18:30:00                80:00:00    NaN
3   2021-11-23 10:00:00            NaN                             NaN     03:00:00

V podstatě, to je to, co já chci, ale jak mohu vyloučit víkendech hodin při výpočtu rozdíl mezi časová razítka od Složka1 a Folder2? Co mám změnit, aby to df, jako je tento:

     Folder1                   Folder2                           Time1     Time2
0   2021-11-22 12:00:00      2021-11-24 10:00:00                46:00:00    NaN
1   2021-11-23 10:30:00      2021-11-25 18:30:00                56:00:00    NaN
2   2021-11-12 10:30:00      2021-11-15 18:30:00                32:00:00    NaN
3   2021-11-23 10:00:00            NaN                            NaN     03:00:00

Takže, v řádku s indexem 2, 13.11. a 14.11 byly víkendy, takže v Době 1 by měl být rozdíl 32 místo 80

dataframe datetime pandas python
2021-11-23 12:10:15
3

Nejlepší odpověď

2

Myslím, že bys mohla využít na pandy.date_range funkce v kombinaci s pandy.tseries.offsety.CustomBusinessHour , jako je tento:

# import pandas and numpy
import pandas as pd
import numpy as np

# construct dataframe
df = pd.DataFrame()
df["Folder1"] = pd.to_datetime(
    pd.Series(
        [
            "2021-11-22 12:00:00",
            "2021-11-23 10:30:00",
            "2021-11-12 10:30:00",
            "2021-11-23 10:00:00",
        ]
    )
)
df["Folder2"] = pd.to_datetime(
    pd.Series(
        [
            "2021-11-24 10:00:00", 
            "2021-11-25 18:30:00", 
            "2021-11-15 18:30:00", 
            np.NaN
        ]
    )
)

# define custom business hours
cbh = pd.tseries.offsets.CustomBusinessHour(start="0:00", end="23:59")

# actual calculation
df["Time1"] = df[~(df["Folder1"].isnull() | df["Folder2"].isnull())].apply(
    lambda row: len(
        pd.date_range(
            start=row["Folder1"], 
            end=row["Folder2"], 
            freq=cbh)),
    axis=1,
)

df.head()

Což je pro mě výnosy:

print(df.head())
              Folder1             Folder2  Time1
0 2021-11-22 12:00:00 2021-11-24 10:00:00   46.0
1 2021-11-23 10:30:00 2021-11-25 18:30:00   56.0
2 2021-11-12 10:30:00 2021-11-15 18:30:00   32.0
3 2021-11-23 10:00:00                 NaT    NaN

Jako bonus si můžete udělat svůj Time2 výpočet efektivněji používat stejně:

df["Time2"] = df[df["Folder2"].isnull()].apply(
    lambda row: len(
        pd.date_range(
            start=row["Folder1"],
            end=datetime.datetime.now(),
            freq=cbh)),
    axis=1,
)

Což je pro mě výnosy (v 14:45 SEČ):

print(df.head())
              Folder1             Folder2  Time1  Time2
0 2021-11-22 12:00:00 2021-11-24 10:00:00   46.0    NaN
1 2021-11-23 10:30:00 2021-11-25 18:30:00   56.0    NaN
2 2021-11-12 10:30:00 2021-11-15 18:30:00   32.0    NaN
3 2021-11-23 10:00:00                 NaT    NaN    5.0
2021-11-23 13:54:11

Ahoj @Jonathan, děkuji vám za odpověď, to funguje v pořádku ale potřebuju sloupce v Time1 a Time2 být zobrazeny také v minutách a sekundách formátu, protože musím vypočítat SLA, takže místo toho, 46.0, můžu ho mít v podobě, jak 46:00:00, protože mám případech, kdy hodnota v Time1 je to takhle: 12:34:23.
user14073111

Ah minul. V tom případě můžete třeba zkombinovat s tímhle: stackoverflow.com/a/40276658/2186184
Jonathan

Navrhuji přepracovat své strfdelta funkce vrátí datetime.timedelta namísto řetězec pomocí datetime.timedelta(seconds=seconds_input)
Jonathan
1
df = pd.DataFrame({'Folder1': ['2021-11-22 12:00:00', '2021-11-23 10:30:00', '2021-11-12 10:30:00', '2021-11-23 10:00:00'],
                   'Folder2': ['2021-11-24 10:00:00', '2021-11-25 18:30:00', '2021-11-15 18:30:00', None]})
df[['Folder1','Folder2']] = df[['Folder1','Folder2']].astype('datetime64')

def strfdelta(t1, t2):
    hd = pd.date_range(t1, t2, freq='W-SAT').append(pd.date_range(t1, t2, freq='W-SUN'))
    sec = (t2-t1).total_seconds() - len(hd)*24*3600
    return f"{int(sec//3600):02d}:{int((sec%3600)//60):02d}:{int(sec%60):02d}"

now = pd.to_datetime('now')
df['Time1'] = df.fillna(now).apply(lambda x: strfdelta(x['Folder1'], x['Folder2']), axis=1)
print(df) 

Tisky:

              Folder1             Folder2     Time1
0 2021-11-22 12:00:00 2021-11-24 10:00:00  46:00:00
1 2021-11-23 10:30:00 2021-11-25 18:30:00  56:00:00
2 2021-11-12 10:30:00 2021-11-15 18:30:00  32:00:00
3 2021-11-23 10:00:00                 NaT  20:58:26
2021-11-23 13:35:17

S nějakou modifikaci na přidávání Time2 sloupec, to je to, co jsem chtěl, díky moc!
user14073111
1
df['Folder1']=pd.to_datetime(df['Folder1'])
df['Folder2']=pd.to_datetime(df['Folder2']).fillna(df['Folder1'])

df['missing']=df.apply(lambda x: pd.date_range(start=x['Folder1'], end=x['Folder2'], freq='D'), axis=1)#Create column with missing date periods



df=(df.assign(time=np.where((df['missing'].apply(lambda x: x.strftime('%w'))).map(set).astype(str).str.contains('0|6'),#Where missing periods have a Saturday or Sunday
                            
                            (df['Folder2']-df['Folder1']).astype('timedelta64[h]')-48,# When above condition is met, subtract two 48 hours from the two days columns difference
                            (df['Folder2']-df['Folder1']).astype('timedelta64[h]'))#When condition not met substract just the two date columns)
             ).drop(columns=['missing']) )             
print(df)



Folder1             Folder2  time
0 2021-11-22 12:00:00 2021-11-24 10:00:00  46.0
1 2021-11-23 10:30:00 2021-11-25 18:30:00  56.0
2 2021-11-12 10:30:00 2021-11-15 18:30:00  32.0
3 2021-11-23 10:00:00 2021-11-23 10:00:00   0.0
2021-11-24 06:59:50

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................