Я уже задавал подобный вопрос (см. Здесь) , но, к сожалению, это было недостаточно ясно, поэтому я решил, что лучше создать новый, например, с лучшим набором данных и новым объяснением желаемый результат - редактирование было бы действительно серьезным изменением.
Итак, у меня есть следующий набор данных (он уже отсортирован по дате и игроку):
d = {'player': ['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3'],
'date': ['2018-01-01 00:17:01', '2018-01-01 00:17:05','2018-01-01 00:19:05', '2018-01-01 00:21:07', '2018-01-01 00:22:09',
'2018-01-01 00:22:17', '2018-01-01 00:25:09', '2018-01-01 00:25:11', '2018-01-01 00:27:28', '2018-01-01 00:29:29',
'2018-01-01 00:30:35', '2018-02-01 00:31:16', '2018-02-01 00:35:22', '2018-02-01 00:38:16',
'2018-02-01 00:38:20', '2018-02-01 00:55:15', '2018-01-03 00:55:22',
'2018-01-03 00:58:16', '2018-01-03 00:58:21', '2018-03-01 01:00:35', '2018-03-01 01:20:16', '2018-03-01 01:31:16'],
'id': [np.nan, np.nan, 'a', 'a', 'b', np.nan, 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'e', 'e', np.nan, 'f', 'f',
'g', np.nan, 'f', 'g']}
#create dataframe
df = pd.DataFrame(data=d)
#change date to datetime
df['date'] = pd.to_datetime(df['date'])
df
player date id
0 1 2018-01-01 00:17:01 NaN
1 1 2018-01-01 00:17:05 NaN
2 1 2018-01-01 00:19:05 a
3 1 2018-01-01 00:21:07 a
4 1 2018-01-01 00:22:09 b
5 1 2018-01-01 00:22:07 NaN
6 1 2018-01-01 00:25:09 b
7 1 2018-01-01 00:25:11 c
8 1 2018-01-01 00:27:28 c
9 1 2018-01-01 00:29:29 c
10 1 2018-01-01 00:30:35 c
11 2 2018-02-01 00:31:16 d
12 2 2018-02-01 00:35:22 d
13 2 2018-02-01 00:38:16 e
14 2 2018-02-01 00:38:20 e
15 2 2018-02-01 00:55:15 NaN
16 3 2018-01-03 00:55:22 f
17 3 2018-01-03 00:58:16 f
18 3 2018-01-03 00:58:21 g
19 3 2018-03-01 01:00:35 NaN
20 3 2018-03-01 01:20:16 f
21 3 2018-03-01 01:31:16 g
Итак, это мои три столбца:
- 'player' - dtype = object
- 'сессия' (объект). Каждый идентификатор сеанса группирует набор действий (то есть строк в наборе данных), которые игроки реализовали в сети.
- 'date' (объект datetime) сообщает нам время, когда было выполнено каждое действие
Проблема в этом наборе данных заключается в том, что у меня есть временные метки для каждого действия, но в некоторых из них отсутствует идентификатор сеанса. Я хочу сделать следующее: для каждого игрока я хочу дать метку идентификатора для пропущенных значений, основываясь на временной шкале. Действия, не имеющие идентификатора, могут быть помечены, если они попадают во временной диапазон (первое действие - последнее действие) определенного сеанса.
Хорошо, вот мои пропущенные значения:
df.loc[df.id.isnull(),'date']
0 2018-01-01 00:17:01
1 2018-01-01 00:17:05
5 2018-01-01 00:22:07
15 2018-02-01 00:55:15
19 2018-03-01 01:00:35
Обратите внимание, что у меня есть код плеера для каждого из них: мне не хватает только сессионного кода. Итак, я хочу сравнить временную метку каждого пропущенного значения с временной меткой сеанса соответствующих игроков.
Я думал о том, чтобы вычислить с помощью группы первое и последнее действие для каждого сеанса, для каждого игрока (но я не знаю, является ли это наилучшим подходом).
my_agg = df.groupby(['player', 'id']).date.agg([min, max])
my_agg
min max
player id
1 a 2018-01-01 00:19:05 2018-01-01 00:21:07
b 2018-01-01 00:22:09 2018-01-01 00:25:09
c 2018-01-01 00:25:11 2018-01-01 00:30:35
2 d 2018-02-01 00:31:16 2018-02-01 00:35:22
e 2018-02-01 00:38:16 2018-02-01 00:38:20
3 f 2018-01-03 00:55:22 2018-03-01 01:20:16
g 2018-01-03 00:58:21 2018-03-01 01:31:16
Тогда я бы хотел сопоставить Nan с идентификатором игрока и сравнить временные метки каждого пропущенного значения с диапазоном каждой сессии для этого игрока.
В наборе данных я пытаюсь проиллюстрировать три возможных сценария, которые меня интересуют:
- действие произошло между первой и последней датой определенного сеанса. В этом случае я хотел бы заполнить отсутствующее значение идентификатором этого сеанса, поскольку он явно принадлежит этому сеансу. Поэтому строка 5 набора данных должна быть помечена как «b», так как она находится в диапазоне b.
- Я бы обозначил как '0' сеанс, в котором действие произошло вне диапазона любого сеанса - например, первые два Nans и строка 15.
- Наконец, отметьте его как '-99', если невозможно связать действие с одним сеансом, поскольку оно произошло во временном диапазоне другого сеанса. Это случай строки 19, последней нан.
Желаемый выход :
Подводя итог, результат должен выглядеть следующим образом:
player date id
0 1 2018-01-01 00:17:01 0
1 1 2018-01-01 00:17:05 0
2 1 2018-01-01 00:19:05 a
3 1 2018-01-01 00:21:07 a
4 1 2018-01-01 00:22:09 b
5 1 2018-01-01 00:22:07 b
6 1 2018-01-01 00:25:09 b
7 1 2018-01-01 00:25:11 c
8 1 2018-01-01 00:27:28 c
9 1 2018-01-01 00:29:29 c
10 1 2018-01-01 00:30:35 c
11 2 2018-02-01 00:31:16 d
12 2 2018-02-01 00:35:22 d
13 2 2018-02-01 00:38:16 e
14 2 2018-02-01 00:38:20 e
15 2 2018-02-01 00:55:15 0
16 3 2018-01-03 00:55:22 f
17 3 2018-01-03 00:58:16 f
18 3 2018-01-03 00:58:21 g
19 3 2018-03-01 01:00:35 -99
20 3 2018-03-01 01:20:16 f
21 3 2018-03-01 01:31:16 g