bugfix> python-3.x > 投稿

私はこのようなDateTimeIndexのパンダdfを持っています:

time
2016-06-10 10:09:16        0.0
2016-06-10 13:18:08    11332.0
2016-06-13 09:00:22        0.0
2016-06-13 10:14:12     4430.0
2016-06-13 13:27:14    11582.0
2016-06-13 15:15:59     6525.0
2016-06-13 16:25:25     4166.0
2016-06-14 09:29:23        0.0
2016-06-14 13:12:31    13388.0
2016-06-14 16:25:28    11577.0

列には、最後の観測/行からの秒数が表示され、次のように毎日リセットされます。

def time_calc(df):
    res = df.index.to_series().diff().dt.seconds.fillna(0)
    df = df.join(res)
    return df
df = df.groupby(df.index.date, group_keys=False).apply(time_calc)

ただし、毎日09:00:00から秒のカウントを開始して、dfが次のようになるようにします。

time
2016-06-10 10:09:16     4156.0
2016-06-10 13:18:08    11332.0
2016-06-13 09:00:22       22.0
2016-06-13 10:14:12     4430.0
2016-06-13 13:27:14    11582.0
2016-06-13 15:15:59     6525.0
2016-06-13 16:25:25     4166.0
2016-06-14 09:29:23     1763.0
2016-06-14 13:12:31    13388.0
2016-06-14 16:25:28    11577.0

これを達成する方法についてのポインタは大歓迎です...

回答 2 件
  • あなたが今何をしたいのか理解しています。これは2つのステップで実行できます。

    最初に、最初の値以外のすべての時間差を計算します。これは groupby で実現できます  + shift 。最初の値は常に NaT に設定されます  そのため、それを 9:00:00 との時間差として設定することができます

    import pandas as pd
    df = df.reset_index()
    df['seconds'] = df.groupby(df.time.dt.date).time.apply(lambda x: x -x.shift(1))
    df.loc[df.seconds.isnull(), 'seconds'] = df.loc[df.seconds.isnull(), 'time'] - pd.to_datetime(df.loc[df.seconds.isnull(), 'time'].astype('str').replace('(?<=\s).*', '9:00:00', regex=True))
    df['seconds'] = df.seconds.dt.total_seconds()
    df = df.set_index('time')
    #                     seconds
    #time                        
    #2016-06-10 10:09:16   4156.0
    #2016-06-10 13:18:08  11332.0
    #2016-06-13 09:00:22     22.0
    #2016-06-13 10:14:12   4430.0
    #2016-06-13 13:27:14  11582.0
    #2016-06-13 15:15:59   6525.0
    #2016-06-13 16:25:25   4166.0
    #2016-06-14 09:29:23   1763.0
    #2016-06-14 13:12:31  13388.0
    #2016-06-14 16:25:28  11577.0
    
    

  • これは最良の答えではないかもしれませんが、うまくいきます。

    タイムデルタを使用してこれを見つけることができます。 Pandas DataframeまたはSeriesが pd.datetimes として保存されていると仮定します 、pd.to_datetime()を使用して実行できます。datetimeから9時間を減算し、そのtimedeltaのすべての秒を取得してから、1日の秒数である86,400でモジュロします。

    pd.to_timedelta(df -  dt.timedelta(hours=9)).dt.total_seconds() % 86400
    
    

    出力が得られます:

    0     4156.0
    1    15488.0
    2       22.0
    3     4452.0
    4    16034.0
    5    22559.0
    6    26725.0
    7     1763.0
    8    15151.0
    9    26728.0
    
    

    次に、リストの内包表記を使用して終了する必要があります。

    s2 = [x-y if d1==d2 else x for x,y,d1,d2 in zip(df.seconds[1:], df.seconds[:-1], my_days[1:], my_days[:-1])]
    s2.insert(0, df.seconds[0])
     4156.0
    11332.0
       22.0
     4430.0
    11582.0
     6525.0
     4166.0
     1763.0
    13388.0
    11577.0
    
    

    浮動小数点数ではなく整数にしたい場合は、 pd.DataFrame.assign() を使用して列に割り当てた後に.astype(int)を使用できます  データフレームの場合、またはシリーズを使用している場合はデータフレームを作成します。インデックスを列にしたい場合は、単に df.reset_index() を使用します 。


    私のインタラクティブセッションは次のようになります:

    import pandas as pd
    import datetime as dt     
    time = [ "2016-06-10 10:09:16", "2016-06-10 13:18:08", "2016-06-13 09:00:22", "2016-06-13 10:14:12", "2016-06-13 13:27:14", "2016-06-13 15:15:59", "2016-06-13 16:25:25", "2016-06-14 09:29:23", "2016-06-14 13:12:31", "2016-06-14 16:25:28"]
    my_time = pd.Series(time)
    my_time = pd.to_datetime(my_time)
    df = pd.DataFrame({
         'datetime':my_time.values, 
         'seconds':pd.to_timedelta(my_time -  dt.timedelta(hours=9)).dt.total_seconds() % 86400
       })
    my_days = df.datetime.dt.day
    s2 = [x-y if d1==d2 else x for x,y,d1,d2 in zip(df.seconds[1:], df.seconds[:-1], my_days[1:], my_days[:-1])]
    s2.insert(0, df.seconds[0])
    df.loc[:, "seconds"] = s2
    print(df)
                 datetime  seconds
    0 2016-06-10 10:09:16   4156.0
    1 2016-06-10 13:18:08  11332.0
    2 2016-06-13 09:00:22     22.0
    3 2016-06-13 10:14:12   4430.0
    4 2016-06-13 13:27:14  11582.0
    5 2016-06-13 15:15:59   6525.0
    6 2016-06-13 16:25:25   4166.0
    7 2016-06-14 09:29:23   1763.0
    8 2016-06-14 13:12:31  13388.0
    9 2016-06-14 16:25:28  11577.0
    
    

あなたの答え