2015-05-23 5 views
2

У меня есть dataframe, в основном с датами. Вот что я хочу сделатьОперация Pandas Column с датами

Из старой переменной даты (DTDate) я хочу создать новую переменную даты, если старая дата - в понедельник, новая дата будет такой же, но если старая дата - любая date, кроме понедельника, новая дата даст мне дату следующего понедельника. Итак, наконец, все элементы новой даты будут только с понедельника.

Я пробовал с функцией и применяю. здесь установлен мои данные и код

Date call DTDate  weekday  weekdayNo 
0 31/12/2014 2014-12-31 Wednesday 3 
1 29/10/2014 2014-10-29 Wednesday 3 
2 28/10/2014 2014-10-28 Tuesday  2 
3 27/3/2015 2015-03-27 Friday  5 
4 27/2/2015 2015-02-27 Friday  5 
5 27/11/2014 2014-11-27 Thursday 4 
6 27/10/2014 2014-10-27 Monday  1 
7 26/3/2015 2015-03-26 Thursday 4 
8 26/2/2015 2015-02-26 Thursday 4 
9 26/12/2014 2014-12-26 Friday  5 
10 26/11/2014 2014-11-26 Wednesday 3 
11 26/10/2014 2014-10-26 Sunday  0 
12 25/3/2015 2015-03-25 Wednesday 3 
13 25/12/2014 2014-12-25 Thursday 4 
14 24/3/2015 2015-03-24 Tuesday  2 
15 24/2/2015 2015-02-24 Tuesday  2 
16 24/12/2014 2014-12-24 Wednesday 3 
17 24/11/2014 2014-11-24 Monday  1 
18 23/3/2015 2015-03-23 Monday  1 

Код

from datetime import date, timedelta 

def AddDate(row): 
    if row['weekdayNo']==0: 
     return row['DTDate'] + timedelta(days=1) 
    elif row['weekdayNo'] ==2: 
     return row['DTDate'] + timedelta(days=6) 
    elif row['weekdayNo'] ==3: 
     return row['DTDate'] + timedelta(days=5) 
    elif row['weekdayNo'] ==4: 
     return row['DTDate'] + timedelta(days=4) 
    elif row['weekdayNo'] ==5: 
     return row['DTDate'] + timedelta(days=3) 
    elif row['weekdayNo'] ==6: 
     return row['DTDate'] + timedelta(days=2) 
    else: 
     return row['DTDate'] 

DF['newDate'] = DF.apply(AddDate, axis=1) 

, и я получаю следующее, это точно то же самое, ничего не изменилось

 Date call DTDate  weekday weekdayNo newDate 
0 31/12/2014 2014-12-31 Wednesday  3  2014-12-31 
1 29/10/2014 2014-10-29 Wednesday  3  2014-10-29 
2 28/10/2014 2014-10-28 Tuesday  2  2014-10-28 
3 27/3/2015 2015-03-27 Friday   5  2015-03-27 
4 27/2/2015 2015-02-27 Friday   5  2015-02-27 
5 27/11/2014 2014-11-27 Thursday  4  2014-11-27 
6 27/10/2014 2014-10-27 Monday   1  2014-10-27 
7 26/3/2015 2015-03-26 Thursday  4  2015-03-26 
8 26/2/2015 2015-02-26 Thursday  4  2015-02-26 
9 26/12/2014 2014-12-26 Friday   5  2014-12-26 
10 26/11/2014 2014-11-26 Wednesday  3  2014-11-26 
11 26/10/2014 2014-10-26 Sunday   0  2014-10-26 
12 25/3/2015 2015-03-25 Wednesday  3  2015-03-25 
13 25/12/2014 2014-12-25 Thursday  4  2014-12-25 
14 24/3/2015 2015-03-24 Tuesday  2  2015-03-24 
15 24/2/2015 2015-02-24 Tuesday  2  2015-02-24 
16 24/12/2014 2014-12-24 Wednesday  3  2014-12-24 
17 24/11/2014 2014-11-24 Monday   1  2014-11-24 
18 23/3/2015 2015-03-23 Monday   1  2015-03-23 

Я также думаю , эта идея не хороша, если есть что-то лучше, пожалуйста, кто-нибудь хотел бы предложить, что это может быть? Заранее спасибо

+0

Является ли 'DF.DTDate' dtype' datetime'? Можете ли вы попробовать преобразовать его в datetime'df.DTDate = pd.to_datetime (DF.DTDate) '? – UNagaswamy

ответ

1

AddDate функция может быть проще, Infact один лайнер

In [34]: df['newDate'] = df['DTDate'].apply(lambda x: x + timedelta(days=7-x.dayofweek) 
              if x.dayofweek else x) 

Здесь функция лямбда lambda x: x + timedelta(days=7-x.dayofweek) if x.dayofweek else x
добавляет дельта = 7-x.dayofweek дней, если это не понедельник.

Для проверки новой weekday позволяет создать новый столбец newdayofweek

In [35]: df['newdayofweek'] = df['newDate'].apply(lambda x: x.dayofweek) 

In [36]: df 
Out[36]: 
    Date  call  DTDate weekday weekdayNo newDate newdayofweek 
0  0 31/12/2014 2014-12-31 Wednesday   3 2015-01-05    0 
1  1 29/10/2014 2014-10-29 Wednesday   3 2014-11-03    0 
2  2 28/10/2014 2014-10-28 Tuesday   2 2014-11-03    0 
3  3 27/3/2015 2015-03-27  Friday   5 2015-03-30    0 
4  4 27/2/2015 2015-02-27  Friday   5 2015-03-02    0 
5  5 27/11/2014 2014-11-27 Thursday   4 2014-12-01    0 
6  6 27/10/2014 2014-10-27  Monday   1 2014-10-27    0 
7  7 26/3/2015 2015-03-26 Thursday   4 2015-03-30    0 
8  8 26/2/2015 2015-02-26 Thursday   4 2015-03-02    0 
9  9 26/12/2014 2014-12-26  Friday   5 2014-12-29    0 
10 10 26/11/2014 2014-11-26 Wednesday   3 2014-12-01    0 
11 11 26/10/2014 2014-10-26  Sunday   0 2014-10-27    0 
12 12 25/3/2015 2015-03-25 Wednesday   3 2015-03-30    0 
13 13 25/12/2014 2014-12-25 Thursday   4 2014-12-29    0 
14 14 24/3/2015 2015-03-24 Tuesday   2 2015-03-30    0 
15 15 24/2/2015 2015-02-24 Tuesday   2 2015-03-02    0 
16 16 24/12/2014 2014-12-24 Wednesday   3 2014-12-29    0 
17 17 24/11/2014 2014-11-24  Monday   1 2014-11-24    0 
18 18 23/3/2015 2015-03-23  Monday   1 2015-03-23    0 

Примечание: день недели с понедельника = 0, воскресенье = 6

+0

Спасибо mate, блестящее решение, но по некоторым причинам я получаю сообщение об ошибке ... '' объект datetime.date 'не имеет атрибута' dayofweek'' какого-либо предложения ?? извините, мой предыдущий комментарий был неправильным –

+0

Является ли ваш 'type (df ['DTDate'] [0]) == pandas.tslib.Timestamp'?Если нет, тогда преобразуйте его 'df ['DTDate'] = pd.to_datetime (df ['DTDate'])' – Zero

+0

нормально..но это сработало ..... отлично .... спасибо большое, большое вам спасибо ? можете ли вы просто предложить что-то прочитать о проблеме 'to_datetime' или когда мне это нужно? Было бы здорово, спасибо много ... или если у вас есть время, можете ли вы объяснить в некоторых словах, может быть? –

2

Вам не нужно import datetime или timedelta к сделай это.

df['DTDate'] = pd.to_datetime(df['DTDate']) # can skip this if column 'DTDate' is already of the right type 

x.weekday() извлекает день недели с понедельника = 0 и воскресенье = 6.

df['newDate'] = df.DTDate.apply(lambda x: x + pd.DateOffset(days=7-x.weekday()) if x.weekday() else x) 

выходы:

Date_call  DTDate weekday weekdayNo newDate 
0 2014-12-31 2014-12-31 Wednesday   3 2015-01-05 
1 2014-10-29 2014-10-29 Wednesday   3 2014-11-03 
2 2014-10-28 2014-10-28 Tuesday   2 2014-11-03 
3 2015-03-27 2015-03-27  Friday   5 2015-03-30 
4 2015-02-27 2015-02-27  Friday   5 2015-03-02 
5 2014-11-27 2014-11-27 Thursday   4 2014-12-01 
6 2014-10-27 2014-10-27  Monday   1 2014-10-27 
7 2015-03-26 2015-03-26 Thursday   4 2015-03-30 
8 2015-02-26 2015-02-26 Thursday   4 2015-03-02 
9 2014-12-26 2014-12-26  Friday   5 2014-12-29 
10 2014-11-26 2014-11-26 Wednesday   3 2014-12-01 
11 2014-10-26 2014-10-26  Sunday   0 2014-10-27 
12 2015-03-25 2015-03-25 Wednesday   3 2015-03-30 
13 2014-12-25 2014-12-25 Thursday   4 2014-12-29 
14 2015-03-24 2015-03-24 Tuesday   2 2015-03-30 
15 2015-02-24 2015-02-24 Tuesday   2 2015-03-02 
16 2014-12-24 2014-12-24 Wednesday   3 2014-12-29 
17 2014-11-24 2014-11-24  Monday   1 2014-11-24 
18 2015-03-23 2015-03-23  Monday   1 2015-03-23 
+1

Спасибо, это тоже отличное решение .... –

0

Здесь гораздо более производительный способ сделать это.

In [50]: s = Series(pd.date_range('20000101',freq='D',periods=10000)) 

In [51]: result = s.where(s.dt.weekday==0,pd.TimedeltaIndex(7-s.dt.weekday,unit='d')+s) 

In [52]: expected = s.apply(lambda x: x + pd.DateOffset(days=7-x.weekday()) if x.weekday() else x) 

In [53]: (result==expected).all() 
Out[53]: True 

Это по существу цикл в пространстве python.

In [54]: %timeit s.apply(lambda x: x + pd.DateOffset(days=7-x.weekday()) if x.weekday() else x) 
1 loops, best of 3: 244 ms per loop 

Здесь мы создаем TimedeltaIndex дней для добавления. .where является эквивалентной идиомой для if-then, но это векторное выражение.

In [55]: %timeit s.where(s.dt.weekday==0,pd.TimedeltaIndex(7-s.dt.weekday,unit='d')+s) 
100 loops, best of 3: 9.69 ms per loop 
Смежные вопросы