時間と分で2つの列間のパンダDataFrame時間差を計算します


85

データフレームに2つの列とがfromdateありますtodate

import pandas as pd

data = {'todate': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000'), pd.Timestamp('2014-01-23 10:07:47.660000')],
        'fromdate': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000'), pd.Timestamp('2014-01-23 18:50:41.420000')]}

df = pd.DataFrame(data)

新しい列を追加して、diffを使用して2つの日付の違いを見つけます

df['diff'] = df['fromdate'] - df['todate']

diff列を取得しましたがdays、24時間を超えると、列が含まれます。

                   todate                fromdate                   diff
0 2014-01-24 13:03:12.050 2014-01-26 23:41:21.870 2 days 10:38:09.820000
1 2014-01-27 11:57:18.240 2014-01-27 15:38:22.540 0 days 03:41:04.300000
2 2014-01-23 10:07:47.660 2014-01-23 18:50:41.420 0 days 08:42:53.760000

結果を時間と分のみに変換するにはどうすればよいですか(つまり、日は時間に変換されます)?

回答:


127

パンダのタイムスタンプの違いは、datetime.timedeltaオブジェクトを返します。これは、次のように* as_type *メソッドを使用して簡単に時間に変換できます。

import pandas
df = pandas.DataFrame(columns=['to','fr','ans'])
df.to = [pandas.Timestamp('2014-01-24 13:03:12.050000'), pandas.Timestamp('2014-01-27 11:57:18.240000'), pandas.Timestamp('2014-01-23 10:07:47.660000')]
df.fr = [pandas.Timestamp('2014-01-26 23:41:21.870000'), pandas.Timestamp('2014-01-27 15:38:22.540000'), pandas.Timestamp('2014-01-23 18:50:41.420000')]
(df.fr-df.to).astype('timedelta64[h]')

得た、

0    58
1     3
2     8
dtype: float64

astypeの回避策は機能しますが、大きな(50万行)ファイルには遅すぎます。他に何か提案はありますか?
student1 2016

3
timedeltaオブジェクトには日と秒の属性があります...そうです、(df.fr-df.to).dt.days * 24 +(df.fr-df.to).dt.seconds / 3600
nitin

1
ありがとうございました!これは、(年齢を取得するために)年を計算するためにも機能しました:df ['age'] =(df ['later_date'] --df ['birth_date'])。astype( 'timedelta64 [Y]')
Superduper

49

.astype()上記の解決策が私にはうまくいかなかったので、これは私をばかげたものにしました。しかし、私は別の方法を見つけました。時間を計ったことはありませんが、他の人のために働くかもしれません:

t1 = pd.to_datetime('1/1/2015 01:00')
t2 = pd.to_datetime('1/1/2015 03:30')

print pd.Timedelta(t2 - t1).seconds / 3600.0

...時間が必要な場合。または:

print pd.Timedelta(t2 - t1).seconds / 60.0

...分が必要な場合。


9
私も同じ問題を抱えていましたが、1日を超える時差は無視され、個別に含める必要があるため、ソリューションでは注意が必要です
ホースシュー

41
私はちょうどそれ.total_seconds()がそれを必要とする人々のために仕事をするのを見つけました
馬蹄形

不思議なことに(私は4年後に気づい)、あなたは括弧を使用する必要が()ため.total_seconds()ではなく.seconds
elPastor

5
  • 結果を時間と分のみに変換するにはどうすればよいですか
    • 受け入れられた回答は、を返すだけdays + hoursです。議事録は含まれていません。
  • 時間と分を含む列を提供するには、hh:mmまたはとしてx hours y minutes、追加の計算と文字列の書式設定が必要になります。
  • この回答は、timedelta数学を使用して合計時間または合計分を浮動小数点数として取得する方法を示しており、使用するよりも高速です.astype('timedelta64[h]')
  • Pandas TimeDeltasユーザーガイド
  • パンダ時系列/日付機能ユーザーガイド
  • Pythontimedeltaオブジェクト:サポートされている操作を参照してください。
import pandas as pd

# test data from OP, with values already in a datetime format
data = {'to_date': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000'), pd.Timestamp('2014-01-23 10:07:47.660000')],
        'from_date': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000'), pd.Timestamp('2014-01-23 18:50:41.420000')]}

# test dataframe; the columns must be in a datetime format; use pandas.to_datetime if needed
df = pd.DataFrame(data)

# add a timedelta column if wanted. It's added here for information only
# df['time_delta_with_sub'] = df.from_date.sub(df.to_date)  # also works
df['time_delta'] = (df.from_date - df.to_date)

# create a column with timedelta as total hours, as a float type
df['tot_hour_diff'] = (df.from_date - df.to_date) / pd.Timedelta(hours=1)

# create a colume with timedelta as total minutes, as a float type
df['tot_mins_diff'] = (df.from_date - df.to_date) / pd.Timedelta(minutes=1)

# display(df)
                  to_date               from_date             time_delta  tot_hour_diff  tot_mins_diff
0 2014-01-24 13:03:12.050 2014-01-26 23:41:21.870 2 days 10:38:09.820000      58.636061    3518.163667
1 2014-01-27 11:57:18.240 2014-01-27 15:38:22.540 0 days 03:41:04.300000       3.684528     221.071667
2 2014-01-23 10:07:47.660 2014-01-23 18:50:41.420 0 days 08:42:53.760000       8.714933     522.896000

他の方法

  • その他のリソースのポッドキャストからの注目事項は、.total_seconds()コア開発者が休暇中に追加およびマージされたため、承認されませんでした。
    • これが他の.total_xx方法がない理由でもあります。
# convert the entire timedelta to seconds
# this is the same as td / timedelta(seconds=1)
(df.from_date - df.to_date).dt.total_seconds()
[out]:
0    211089.82
1     13264.30
2     31373.76
dtype: float64

# get the number of days
(df.from_date - df.to_date).dt.days
[out]:
0    2
1    0
2    0
dtype: int64

# get the seconds for hours + minutes + seconds, but not days
# note the difference from total_seconds
(df.from_date - df.to_date).dt.seconds
[out]:
0    38289
1    13264
2    31373
dtype: int64

その他のリソース

%%timeit テスト

import pandas as pd

# dataframe with 2M rows
data = {'to_date': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000')], 'from_date': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000')]}
df = pd.DataFrame(data)
df = pd.concat([df] * 1000000).reset_index(drop=True)

%%timeit
(df.from_date - df.to_date) / pd.Timedelta(hours=1)
[out]:
43.1 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
(df.from_date - df.to_date).astype('timedelta64[h]')
[out]:
59.8 ms ± 1.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.