У меня есть большой фрейм данных (1 м+ строк), который содержит тестовые данные. Моментальный снимок «События» был сделан в разное время, и в каждый моментальный снимок к фрейму данных добавлялось до трех строк. Например, в выдержке ниже первый снимок для события At223 был сделан 18.03.2016 18:10:45, второй — 21.03.2016 10:14:28 и т. д.
Я хочу отфильтровать фрейм данных, чтобы он возвращал только последние n снимков на Ref. Рефы уникальны, тогда как События могут дублироваться.
Я новичок в Pandas, но пробовал различные комбинации sort_values, groupby и tail, но не могу получить желаемый результат. Например:
df = df.sort_values(['Ref', 'Time']).groupby(['Time', 'Ref', 'TestId']).tail(3)
Кто-нибудь может подсказать, как это сделать? В приведенном ниже примере желаемого результата n = 3, поэтому он показывает последние три снимка по Ref.
Извлекать:
Желаемый результат:
Почему желаемый результат содержит более 3 записей для Ref 1.123717985?
Был ли ответ на ваш вопрос?






Вы можете пройтись по каждому уникальному событию и взять верхнее n раз из каждого. Затем объедините результаты вместе:
n = 3
event_dfs = []
for event in df['Event'].unique():
sub_df = df.loc[df['Event'] == event]
max_times = sub_df['Time'].nlargest(n=n)
event_dfs.append(sub_df.loc[sub_df['Time'].isin(max_times)])
result = pd.concat(event_dfs)
Факторизируйте дату и сохраните n самых высоких значений (при условии, что ваш фрейм данных уже отсортирован по времени)
# Number of snapshot you want to keep
n = 3
# Create a boolean mask
m = (df.assign(val=pd.factorize(df['Time'])[0])
.groupby('Ref')['val']
.transform(lambda x: x.max() - x < n))
out = df[m]
Выход:
>>> out
Time Ref Event EndTime TestId TestNames Result
9 21/03/2016 13:05:16 1.123718 At223 01/04/2016 16:00 28212 One NaN
10 21/03/2016 13:05:16 1.123718 At223 01/04/2016 16:00 466299 Two 4.50
11 21/03/2016 13:05:16 1.123718 At223 01/04/2016 16:00 58805 Three NaN
12 21/03/2016 13:14:22 1.123718 At223 01/04/2016 16:00 28212 One NaN
13 21/03/2016 13:14:22 1.123718 At223 01/04/2016 16:00 466299 Two 4.50
14 21/03/2016 13:14:22 1.123718 At223 01/04/2016 16:00 58805 Three NaN
15 01/04/2016 10:37:43 1.123718 At223 01/04/2016 16:00 28212 One NaN
16 01/04/2016 10:37:43 1.123718 At223 01/04/2016 16:00 466299 Two 4.50
17 01/04/2016 10:37:43 1.123718 At223 01/04/2016 16:00 58805 Three NaN
21 21/03/2016 13:03:48 1.123720 Br12 03/04/2016 16:00 28214 Eight 7.20
22 21/03/2016 13:03:48 1.123720 Br12 03/04/2016 16:00 1212772 Nine 1.58
23 21/03/2016 13:03:48 1.123720 Br12 03/04/2016 16:00 58805 Ten 4.40
24 21/03/2016 13:19:15 1.123720 Br12 03/04/2016 16:00 28214 Eight 7.20
25 21/03/2016 13:19:15 1.123720 Br12 03/04/2016 16:00 1212772 Nine 1.58
26 21/03/2016 13:19:15 1.123720 Br12 03/04/2016 16:00 58805 Ten 4.50
27 01/04/2016 12:48:13 1.123720 Br12 03/04/2016 16:00 28214 Eight 7.20
28 01/04/2016 12:48:13 1.123720 Br12 03/04/2016 16:00 1212772 Nine 1.59
29 01/04/2016 12:48:13 1.123720 Br12 03/04/2016 16:00 58805 Ten 4.50
Вы можете использовать apply после groupby
И создайте функцию, которая обрабатывает кадры данных только с одним Ref
def extract_n_last_times(n: int):
def extract_last_times(group: pd.DataFrame):
times = group.sort_values("Time")["Time"].unique()
return group[group["Time"].isin(times[-n:])]
return extract_last_times
df.sort_values(["Ref", "Time"]).groupby("Ref", group_keys=False).apply(extract_n_last_times(n=3))
Кажется, на снимок всегда приходится 3 строки?