DataFrameパンダの日付間の日数を含む列を追加する


95

「B」の日付から「A」の日付を差し引いて、差のある新しい列を追加します。

df
          A        B
one 2014-01-01  2014-02-28 
two 2014-02-03  2014-03-01

以下を試しましたが、これをforループに含めようとするとエラーが発生します...

import datetime
date1=df['A'][0]
date2=df['B'][0]
mdate1 = datetime.datetime.strptime(date1, "%Y-%m-%d").date()
rdate1 = datetime.datetime.strptime(date2, "%Y-%m-%d").date()
delta =  (mdate1 - rdate1).days
print delta

私は何をすべきか?

回答:


96

これらが日付時刻列であると想定すると(それらが適用されない場合to_datetime)、それらを減算できます。

df['A'] = pd.to_datetime(df['A'])
df['B'] = pd.to_datetime(df['B'])

In [11]: df.dtypes  # if already datetime64 you don't need to use to_datetime
Out[11]:
A    datetime64[ns]
B    datetime64[ns]
dtype: object

In [12]: df['A'] - df['B']
Out[12]:
one   -58 days
two   -26 days
dtype: timedelta64[ns]

In [13]: df['C'] = df['A'] - df['B']

In [14]: df
Out[14]:
             A          B        C
one 2014-01-01 2014-02-28 -58 days
two 2014-02-03 2014-03-01 -26 days

注:新しいパンダ(0.10.1など)を使用していることを確認してください。古いバージョンでは機能しない場合があります。


21
数値を見なければならない場合に備えて、結果の「日」の部分を取り除くことはできますか?この場合、-58、-26。
2014年

6
@AndyHaydenコメントを拡張すると、それは機能しますが、pd.offsets.Day(1)( 's'で)機能するはずです。私も通常それを否定するので、あなたは得る(df['A'] - df['B']) / pd.offsets.Day(-1)
dirkjot

11
ただし、シリーズ全体でこれを実行する場合(df['A'] - df['B']) / np.timedelta64(-1, 'D')は、私が完全に理解していない理由で必要になります。
dirkjot 2015年

@dirkjotタイプミスを見つけてくれてありがとう!IIRCこれは最近のパンダで修正されましたが、0.16.2 / 0.17を使用していますか?
アンディヘイデン、

データが欠落している場合、これは少しバグがあることがわかりました。問題は、1)欠落しているデータに.isnull()属性がないこと、および2).dayデータがあるが、欠落していないデータには.days属性があることです。だから、新しい変数を作成した後、私はそれぞれをループ走っobs:チェックというervationをif hasattr(obs,'days')[割り当てobs.days、他の割り当てnp.nan
webelo

101

「日」テキスト要素を削除するには、シリーズのdt()アクセサーを使用することもできます。 https //pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.dt.html

そう、

df[['A','B']] = df[['A','B']].apply(pd.to_datetime) #if conversion required
df['C'] = (df['B'] - df['A']).dt.days

これは次を返します:

             A          B   C
one 2014-01-01 2014-02-28  58
two 2014-02-03 2014-03-01  26

2
すばらしい答えです。私の場合、機能df['C'] = (df['B'] - df['A']).dt.daysせず、を使用する必要がありましたdf['C'] = (df['B'] - df['A']).days。私がなぜ期待した日数を与えなかったのですか?
Samuel Nde 2018

Nde-どのようにして正確に機能しませんでしたか?エラーまたは間違った値?A列とB列の両方を正常に日時に変換しましたか?
リッキーマクマスター

1
私の列は両方とも日時です(datetime64[ns]正確には)。実行するとdf['C'] = (df['B'] - df['A']).dt.daysAttributeError: 'Timedelta'オブジェクトには属性 'dt'がないという属性エラーが発生したため、df ['C'] =(df ['B']-df ['A'])を試しました希望の答えをくれた。(もちろん、私は上の例のデータフレームではなく、自分のデータフレームを使用しています。それとも、日付に時間がないためである可能性があります。2018-09-24 10:17:18.800277
Samuel Nde

1
完璧な答え。
user3065757

1
素晴らしいソリューション。ありがとう!
Rodrigo Hjort

10

リスト内包表記は、これを行う最もPythonic(かつ最速)の方法に対する最善の策です。

[int(i.days) for i in (df.B - df.A)]
  1. timedeltaを返します(例: '-58日')
  2. i.daysはこの値を長整数値として返します(例-58L)
  3. int(i.days)は、求める-58を提供します。

列が日時形式でない場合。短い構文は次のようになります。df.A = pd.to_datetime(df.A)


1

これはどう:

times['days_since'] = max(list(df.index.values))  
times['days_since'] = times['days_since'] - times['months']  
times
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.