2015-05-19 176 views
4

我有一個數據幀DF有如下2列 -添加個月到datetime列在熊貓

   START_DATE    MONTHS 
0    2015-03-21    240 
1    2015-03-21    240 
2    2015-03-21    240 
3    2015-03-21    240 
4    2015-03-21    240 
5    2015-01-01    120 
6    2017-01-01    240 
7      NaN    NaN 
8      NaN    NaN 
9      NaN    NaN 

2列的數據類型是對象。

>>> df.dtypes 
START_DATE object 
MONTHS  object 
dtype: object 

現在,我希望通過添加DF [ 'START_DATE'] & DF ['個月],以創建新列 「結果」。所以,我也做了以下 -

from dateutil.relativedelta import relativedelta 

df['START_DATE'] = pd.to_datetime(df['START_DATE']) 
df['MONTHS'] = df['MONTHS'].astype(float) 

df['offset'] = df['MONTHS'].apply(lambda x: relativedelta(months=x)) 

df['Result'] = df['START_DATE'] + df['offset'] 

在這裏,我得到下面的錯誤 -

TypeError: incompatible type [object] for a datetime/timedelta operation 

注:本想轉換DF [「月」]爲int,但不會作爲工作場有空。

您能否請給我一些指示。謝謝。

+0

你得到哪些錯誤?請發佈錯誤報告。 –

+0

@Borja - 嗨。在我的編輯上面添加了錯誤。謝謝。 – 0nir

回答

6

這是一個矢量化的方式來做到這一點,所以應該是相當高效的。請注意,它不處理月份交叉/結尾(並且不能很好地處理DST更改,我相信這就是您獲得時間的原因)。

In [32]: df['START_DATE'] + df['MONTHS'].values.astype("timedelta64[M]") 
Out[32]: 
0 2035-03-20 20:24:00 
1 2035-03-20 20:24:00 
2 2035-03-20 20:24:00 
3 2035-03-20 20:24:00 
4 2035-03-20 20:24:00 
5 2024-12-31 10:12:00 
6 2036-12-31 20:24:00 
7     NaT 
8     NaT 
9     NaT 
Name: START_DATE, dtype: datetime64[ns] 

如果您需要確切的MonthEnd/Begin處理,這是一個合適的方法。 (使用MonthsOffset拿到當天)

In [33]: df.dropna().apply(lambda x: x['START_DATE'] + pd.offsets.MonthEnd(x['MONTHS']), axis=1) 
Out[33]: 
0 2035-02-28 
1 2035-02-28 
2 2035-02-28 
3 2035-02-28 
4 2035-02-28 
5 2024-12-31 
6 2036-12-31 
dtype: datetime64[ns] 
1

如果您的數據框較小,請使用以下內容。我已經使用axis=1,這是行明智的操作。如果你的數據幀很大,它會很慢

> df['offset'] = df.dropna().apply(lambda v: relativedelta(months=int(v['MONTHS'])) + v['START_DATE'], axis=1) 
> df 
    START_DATE MONTHS  offset 
0 2015-03-21  240 2035-03-21 
1 2015-03-21  240 2035-03-21 
2 2015-03-21  240 2035-03-21 
3 2015-03-21  240 2035-03-21 
4 2015-03-21  240 2035-03-21 
5 2015-01-01  120 2025-01-01 
6 2017-01-01  240 2037-01-01 
7  NaT  NaN  NaT 
8  NaT  NaN  NaT 
9  NaT  NaN  NaT 
+0

它的工作。謝謝。 – 0nir

1

這裏有一種方法來做到這一點,沒有dateutil.relativedelta。請注意,我將MONTHS轉換爲一個整數(並且僅在刪除空值之後,因爲int不接受空值),因爲我想每年進行12個月的整數除法,利用商是年數增量的事實,模/餘數是幾個月內的增量。

import pandas as pd 

df = pd.DataFrame({'START_DATE':['2015-03-21','2015-03-21','2015-03-21','2015-03-21', 
           '2015-03-21','2015-01-01','2017-01-01', None,None,None], 
        'MONTHS':[240,240,240,240,240,120,240,None,None,None]}, 
        dtype='object') # replicate example data 

df.dropna(inplace=True) # drop nulls so can convert MONTHS to int 
df['START_DATE'] = pd.to_datetime(df['START_DATE']) 
df['MONTHS'] = df.MONTHS.astype(int) 

df.apply(lambda x: pd.datetime(x.START_DATE.year + x.MONTHS/12, 
           x.START_DATE.month + x.MONTHS % 12, 
           x.START_DATE.day), axis=1) 
0

這裏是另一個矢量 numpy的解決方案:

In [111]: mask = (df.START_DATE.notnull() & df.MONTHS.notnull()) 

In [112]: df.loc[mask, 'Result'] = (
    ...:  df.START_DATE.loc[mask].values.astype('M8[M]') + \ 
    ...:  (df.MONTHS.loc[mask].values.astype(int) * np.timedelta64(1, 'M')) 
    ...:).astype('M8[D]') - np.timedelta64(1, 'D') 
    ...: 

In [113]: df 
Out[113]: 
    START_DATE MONTHS  Result 
0 2015-03-21 240.0 2035-02-28 
1 2015-03-21 240.0 2035-02-28 
2 2015-03-21 240.0 2035-02-28 
3 2015-03-21 240.0 2035-02-28 
4 2015-03-21 240.0 2035-02-28 
5 2015-01-01 120.0 2024-12-31 
6 2017-01-01 240.0 2036-12-31 
7  NaT  NaN  NaT 
8  NaT  NaN  NaT 
9  NaT  NaN  NaT