Как группировать строки на основе столбцов даты первого и последнего просмотра для каждого идентификатора и перенаправлять значения N / A с использованием Python?

#python #pandas

#python #pandas

Вопрос:

У меня есть следующий фрейм данных:

Фрейм данных

Здесь как Hotel_id, так и Chef_Id уникальны (оба могут выступать в качестве первичного ключа).

Мне нужно заполнить недостающие строки в столбце Month_Year (следует добавить последовательный month_year между первой и последней датой для каждого идентификатора, а затем перенаправить другие соответствующие значения столбца, мне нужно что-то вроде этого:

Ожидаемый фрейм данных

Здесь я объяснил несколько идентификаторов, но мне нужно применить эту концепцию для каждого идентификатора во фрейме данных.

Пожалуйста, дайте мне знать решение.


@r-новички, пожалуйста, найдите приведенные ниже данные для справки:

 Hotel_id    Month_Year      last_review_date
2400614     May-2015        March-2016
2400614     June-2015       March-2016
2400614     December-2015   March-2016
2400614     January-2016    March-2016
2400614     March-2016      March-2016
2400133     April-2016      May-2017
2400133     June-2016       May-2017
2400133     August-2016     May-2017
2400133     January-2017    May-2017
2400133     April-2017      May-2017
2400133     May-2017        May-2017
2400178     June-2015       April-2018
2400178     July-2016       April-2018
2400178     August-2016     April-2018
2400178     January-2017    April-2018
2400178     March-2017      April-2018
2400178     April-2018      April-2018
  

Ответ №1:

Использовать GroupBy.transform с GroupBy.last :

 df['last_review_date'] = df.groupby('Hotel_id')['Month_Year'].transform('last')
print (df)
    Hotel_id     Month_Year last_review_date
0    2400614       May-2015       March-2016
1    2400614      June-2015       March-2016
2    2400614  December-2015       March-2016
3    2400614   January-2016       March-2016
4    2400614     March-2016       March-2016
5    2400133     April-2016         May-2017
6    2400133      June-2016         May-2017
7    2400133    August-2016         May-2017
8    2400133   January-2017         May-2017
9    2400133     April-2017         May-2017
10   2400133       May-2017         May-2017
11   2400178      June-2015       April-2018
12   2400178      July-2016       April-2018
13   2400178    August-2016       April-2018
14   2400178   January-2017       April-2018
15   2400178     March-2017       April-2018
16   2400178     April-2018       April-2018
  

Другая идея — преобразовать значения в datetimes и вернуть максимальные значения для групп
:

 df['Month_Year'] = pd.to_datetime(df['Month_Year'], format='%B-%Y')

df['last_review_date'] = df.groupby('Hotel_id')['Month_Year'].transform('max')
print (df)
    Hotel_id Month_Year last_review_date
0    2400614 2015-05-01       2016-03-01
1    2400614 2015-06-01       2016-03-01
2    2400614 2015-12-01       2016-03-01
3    2400614 2016-01-01       2016-03-01
4    2400614 2016-03-01       2016-03-01
5    2400133 2016-04-01       2017-05-01
6    2400133 2016-06-01       2017-05-01
7    2400133 2016-08-01       2017-05-01
8    2400133 2017-01-01       2017-05-01
9    2400133 2017-04-01       2017-05-01
10   2400133 2017-05-01       2017-05-01
11   2400178 2015-06-01       2018-04-01
12   2400178 2016-07-01       2018-04-01
13   2400178 2016-08-01       2018-04-01
14   2400178 2017-01-01       2018-04-01
15   2400178 2017-03-01       2018-04-01
16   2400178 2018-04-01       2018-04-01
  

Если нужен оригинальный формат datetimes:

 dates = pd.to_datetime(df['Month_Year'], format='%B-%Y')

df['last_review_date'] = dates.groupby(df['Hotel_id']).transform('max').dt.strftime('%B-%Y')
print (df)
    Hotel_id     Month_Year last_review_date
0    2400614       May-2015       March-2016
1    2400614      June-2015       March-2016
2    2400614  December-2015       March-2016
3    2400614   January-2016       March-2016
4    2400614     March-2016       March-2016
5    2400133     April-2016         May-2017
6    2400133      June-2016         May-2017
7    2400133    August-2016         May-2017
8    2400133   January-2017         May-2017
9    2400133     April-2017         May-2017
10   2400133       May-2017         May-2017
11   2400178      June-2015       April-2018
12   2400178      July-2016       April-2018
13   2400178    August-2016       April-2018
14   2400178   January-2017       April-2018
15   2400178     March-2017       April-2018
16   2400178     April-2018       April-2018
  

Редактировать:

При необходимости добавьте все существующие даты месяцев для использования группами:

 df['Month_Year'] = pd.to_datetime(df['Month_Year'], format='%B-%Y')

df1 = (df.set_index('Month_Year')
         .groupby('Hotel_id')
         .resample('1M')
         .ffill()
         .reset_index(level=0, drop=True)
         .reset_index())
  

 print (df1)
   Month_Year  Hotel_id
0  2016-04-30   2400133
1  2016-05-31   2400133
2  2016-06-30   2400133
3  2016-07-31   2400133
4  2016-08-31   2400133
5  2016-09-30   2400133
6  2016-10-31   2400133
7  2016-11-30   2400133
8  2016-12-31   2400133
9  2017-01-31   2400133
10 2017-02-28   2400133
11 2017-03-31   2400133
12 2017-04-30   2400133
13 2017-05-31   2400133
14 2015-06-30   2400178
15 2015-07-31   2400178
16 2015-08-31   2400178
17 2015-09-30   2400178
18 2015-10-31   2400178
19 2015-11-30   2400178
20 2015-12-31   2400178
21 2016-01-31   2400178
22 2016-02-29   2400178
23 2016-03-31   2400178
24 2016-04-30   2400178
25 2016-05-31   2400178
26 2016-06-30   2400178
27 2016-07-31   2400178
28 2016-08-31   2400178
29 2016-09-30   2400178
30 2016-10-31   2400178
31 2016-11-30   2400178
32 2016-12-31   2400178
33 2017-01-31   2400178
34 2017-02-28   2400178
35 2017-03-31   2400178
36 2017-04-30   2400178
37 2017-05-31   2400178
38 2017-06-30   2400178
39 2017-07-31   2400178
40 2017-08-31   2400178
41 2017-09-30   2400178
42 2017-10-31   2400178
43 2017-11-30   2400178
44 2017-12-31   2400178
45 2018-01-31   2400178
46 2018-02-28   2400178
47 2018-03-31   2400178
48 2018-04-30   2400178
49 2015-05-31   2400614
50 2015-06-30   2400614
51 2015-07-31   2400614
52 2015-08-31   2400614
53 2015-09-30   2400614
54 2015-10-31   2400614
55 2015-11-30   2400614
56 2015-12-31   2400614
57 2016-01-31   2400614
58 2016-02-29   2400614
59 2016-03-31   2400614
  

Комментарии:

1. Основной целью вопроса является процесс заполнения недостающих лет и заполнения значений.

Ответ №2:

Я написал код, используя некоторые данные, которые вы представили в качестве образца данных. Используйте as.freq() для заполнения недостающих данных и method='ffill' для определения способа заполнения недостающих данных. Если ваши полные данные ошибочны, вы можете объединить данные, полученные таким образом, с исходными данными.

 import pandas as pd
import numpy as np
import io

data = '''
 Hotel_id Month_Year last_review_date
2400614 May-2015 March-2016
2400614 June-2015 March-2016
2400614 December-2015 March-2016
2400614 January-2016 March-2016
2400614 March-2016 March-2016
2400133 April-2016 May-2017
2400133 June-2016 May-2017
2400133 August-2016 May-2017
2400133 January-2017 May-2017
2400133 April-2017 May-2017
2400133 May-2017 May-2017
2400178 June-2015 April-2018
2400178 July-2016 April-2018
2400178 August-2016 April-2018
2400178 January-2017 April-2018
2400178 March-2017 April-2018
2400178 April-2018 April-2018
'''

df = pd.read_csv(io.StringIO(data), sep='s ')
df['Month_Year'] = pd.to_datetime(df['Month_Year'], format='%B-%Y')
hid = df['Hotel_id'].unique().tolist()
new = pd.DataFrame()
for h in hid:
    tmp = df[df['Hotel_id'] == h].set_index('Month_Year').asfreq('1M', method='ffill')
    new = pd.concat([new, tmp], axis=0)

new
    Hotel_id    last_review_date
Month_Year      
2015-05-31  2400614 March-2016
2015-06-30  2400614 March-2016
2015-07-31  2400614 March-2016
2015-08-31  2400614 March-2016
2015-09-30  2400614 March-2016
2015-10-31  2400614 March-2016
2015-11-30  2400614 March-2016
2015-12-31  2400614 March-2016
2016-01-31  2400614 March-2016
2016-02-29  2400614 March-2016
2016-04-30  2400133 May-2017
2016-05-31  2400133 May-2017
2016-06-30  2400133 May-2017
2016-07-31  2400133 May-2017
2016-08-31  2400133 May-2017
2016-09-30  2400133 May-2017
2016-10-31  2400133 May-2017
2016-11-30  2400133 May-2017
2016-12-31  2400133 May-2017
2017-01-31  2400133 May-2017
2017-02-28  2400133 May-2017
2017-03-31  2400133 May-2017
2017-04-30  2400133 May-2017
2015-06-30  2400178 April-2018
2015-07-31  2400178 April-2018
2015-08-31  2400178 April-2018
2015-09-30  2400178 April-2018
2015-10-31  2400178 April-2018
2015-11-30  2400178 April-2018
2015-12-31  2400178 April-2018
2016-01-31  2400178 April-2018
2016-02-29  2400178 April-2018
2016-03-31  2400178 April-2018
2016-04-30  2400178 April-2018
2016-05-31  2400178 April-2018
2016-06-30  2400178 April-2018
2016-07-31  2400178 April-2018
2016-08-31  2400178 April-2018
2016-09-30  2400178 April-2018
2016-10-31  2400178 April-2018
2016-11-30  2400178 April-2018
2016-12-31  2400178 April-2018
2017-01-31  2400178 April-2018
2017-02-28  2400178 April-2018
2017-03-31  2400178 April-2018
2017-04-30  2400178 April-2018
2017-05-31  2400178 April-2018
2017-06-30  2400178 April-2018
2017-07-31  2400178 April-2018
2017-08-31  2400178 April-2018
2017-09-30  2400178 April-2018
2017-10-31  2400178 April-2018
2017-11-30  2400178 April-2018
2017-12-31  2400178 April-2018
2018-01-31  2400178 April-2018
2018-02-28  2400178 April-2018
2018-03-31  2400178 April-2018
  

Комментарии:

1. Спасибо за ваш ответ! Но у меня возникла проблема, поскольку столбец Month_Year может иметь дубликаты для каждого идентификатора, он выдает ошибку- ValueError: невозможно переиндексировать неуникальный индекс с помощью метода или ограничения

2. Пожалуйста, обновите вопрос в текстовом формате с частичными образцами данных, где можно идентифицировать прокомментированные события.

3. Код был изменен с учетом повторно опубликованных данных. Как указано, произошла ошибка, поэтому я исправил ее в единицах ‘Hotel_id’ и объединил каждую из них.