Tambahkan kolom dengan jumlah hari antara tanggal di panda DataFrame

103

Saya ingin mengurangi tanggal di 'A' dari tanggal di 'B' dan menambahkan kolom baru dengan perbedaannya.

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

Saya sudah mencoba yang berikut ini, tetapi mendapatkan kesalahan ketika saya mencoba memasukkan ini ke dalam for loop ...

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

Apa yang harus saya lakukan?

Jase Villam
sumber

Jawaban:

102

Dengan asumsi ini adalah kolom tanggal waktu (jika tidak berlaku to_datetime), Anda bisa menguranginya:

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

Catatan: pastikan Anda menggunakan pandas baru (mis. 0.13.1), ini mungkin tidak bekerja di versi yang lebih lama.

Andy Hayden
sumber
24
Apakah kita bisa menghilangkan bagian "hari" dalam hasil jika kita hanya perlu melihat nilai numerik yaitu. -58, -26 dalam kasus ini.
0nir
6
untuk memperluas komentar @AndyHayden, yang berfungsi tetapi seharusnya pd.offsets.Day(1)(dengan 's'). Saya juga biasanya meniadakannya, jadi Anda mendapatkan(df['A'] - df['B']) / pd.offsets.Day(-1)
dirkjot
12
Namun, jika Anda ingin melakukan ini pada seluruh Seri, Anda memerlukan (df['A'] - df['B']) / np.timedelta64(-1, 'D')alasan yang saya tidak sepenuhnya mengerti.
dirkjot
@dirkjot Terima kasih telah menemukan kesalahan ketik! IIRC ini telah diperbaiki di panda baru-baru ini, apakah Anda menggunakan 0.16.2 / 0.17?
Andy Hayden
3
@webelo DatetimeIndex / Series itu sendiri harus memiliki .dt.daysatribut yang sangat disukai.
Andy Hayden
115

Untuk menghapus elemen teks 'hari', Anda juga dapat menggunakan pengakses dt () untuk rangkaian: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.dt.html

Begitu,

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

yang mengembalikan:

             A          B   C
one 2014-01-01 2014-02-28  58
two 2014-02-03 2014-03-01  26
Ricky McMaster
sumber
3
Jawaban yang bagus. Dalam kasus saya, df['C'] = (df['B'] - df['A']).dt.daystidak berhasil dan saya harus menggunakan df['C'] = (df['B'] - df['A']).days. Adakah ide mengapa saya tidak memberikan jumlah hari seperti yang diharapkan?
Samuel Nde
Nde - bagaimana tepatnya itu tidak berhasil? Kesalahan atau nilai yang salah? Apakah Anda berhasil mengonversi kolom A dan B ke tanggal waktu?
Ricky McMaster
1
Kedua kolom saya adalah tanggal waktu (atau datetime64[ns]tepatnya). Ketika saya melakukannya df['C'] = (df['B'] - df['A']).dt.days, saya mendapat kesalahan atribut yang mengatakan AttributeError: Objek 'Timedelta' tidak memiliki atribut 'dt' , jadi saya mencoba df ['C'] = (df ['B'] - df ['A']). hari yang memberi saya jawaban yang diinginkan. (Tentu saja saya menggunakan kerangka data saya sendiri bukan dengan contoh di atas. Atau mungkinkah karena saya juga punya waktu di kencan saya dan bukan seperti di 2018-09-24 10:17:18.800277)
Samuel Nde
1
jawaban yang sempurna.
pengguna3065757
1
Solusi bagus. Terima kasih!
Rodrigo Hjort
11

Pemahaman daftar adalah taruhan terbaik Anda untuk cara paling Pythonic (dan tercepat) untuk melakukan ini:

[int(i.days) for i in (df.B - df.A)]
  1. saya akan mengembalikan timedelta (misalnya '-58 hari')
  2. i.days akan mengembalikan nilai ini sebagai nilai integer panjang (misalnya -58L)
  3. int (i.days) akan memberi Anda -58 yang Anda cari.

Jika kolom Anda tidak dalam format datetime. Sintaks yang lebih pendek adalah:df.A = pd.to_datetime(df.A)

A.Kot
sumber
1

Bagaimana dengan ini:

times['days_since'] = max(list(df.index.values))  
times['days_since'] = times['days_since'] - times['months']  
times
Tom
sumber