#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
У меня есть такой набор данных (дополнительный здесь означает несколько дополнительных столбцов):
>>> df = pd.DataFrame({'id_police':['p123','p123','p123','b123','b123'],
'dateeffe':['24/01/2018','24/11/2017','25/02/2018','24/02/2018','24/02/2018'],
'date_fin':['23/03/2018','23/12/2017','26/03/2018','25/02/2018','25/02/2018'],
'prime':[0,20,10,20,30],
'prime2':[0,30,10,20,0],
'extra':[12,12,13,15,20],
...
})
###
id_police dateeffe date_fin prime prime2 extra ...
0 p123 24/01/2018 23/03/2018 0 0 12 ...
1 p123 24/11/2017 23/12/2017 20 30 12 ...
2 p123 25/02/2018 26/03/2018 10 10 13 ...
3 b123 24/02/2018 25/02/2018 20 20 15 ...
4 b123 24/02/2018 25/02/2018 30 0 20 ...
Я хочу отсортировать даты (например, 2017, затем 2018 …) в каждом столбце id_police
, кроме того, мне придется сохранять максимальное число в каждом дубликате dateeffe
и date_fin
, как в 3 и 4, иметь то же id_police
самое.
Это ожидаемый результат:
id_police dateeffe date_fin prime prime2 extra ...
0 p123 24/11/2017 23/12/2017 20 30 12 ...
1 p123 24/01/2018 23/03/2018 0 0 12 ...
2 p123 25/02/2018 26/03/2018 10 10 13 ...
3 b123 24/02/2018 25/02/2018 30 20 15 ...
Чтобы найти максимальное простое число и prime2, я использовал это:
df = df.groupby(['id_police','dateeffe','date_fin'],as_index=False).agg({'prime':'max','prime2':'max'})
Это то, что я пробовал, но оно группирует все, и я теряю дополнительный столбец…
df1 = df.sort_values(['dateeffe','date_fin']).groupby('id_police', as_index=False).apply(lambda x: x)
Я искал везде и ценю вашу помощь, заранее спасибо!
Комментарии:
1. вопрос, prime2 20 больше 0, а prime1 30 больше 20, со стороны ранга они имеют одинаковый вес, почему вы выбираете строку 3, а не строку 4
2. на самом деле идентификатор сбрасывается в этом случае, и ни один из них не выбран, я выбрал максимум в каждой строке для одних и тех же дат
3. Хорошо, просто позвольте мне упростить вопрос, почему строка 4 удаляется?
4. строка 4 не выбрана, я выбираю максимум для каждого столбца для prime amp; prime2. но сохраните другие детали, которые дублируются, как даты.
Ответ №1:
Проверьте вывод с помощью first
df = df.groupby(['id_police','dateeffe','date_fin'],as_index=False).agg({'prime':'max','prime2':'max','extra':'first'})
df
Out[482]:
id_police dateeffe date_fin prime prime2 extra
0 b123 24/02/2018 25/02/2018 30 20 15
1 p123 24/01/2018 23/03/2018 0 0 12
2 p123 24/11/2017 23/12/2017 20 30 12
3 p123 25/02/2018 26/03/2018 10 10 13
Обновить
d={'prime':'max','prime2':'max'}
d1=dict.fromkeys(df.columns.difference(['id_police','dateeffe','date_fin','prime','prime2']),'first')
d.update(d1)
df=df.groupby(['id_police','dateeffe','date_fin'],as_index=False).agg(d)
Out[501]:
id_police dateeffe date_fin prime prime2 extra
0 b123 24/02/2018 25/02/2018 30 20 15
1 p123 24/01/2018 23/03/2018 0 0 12
2 p123 24/11/2017 23/12/2017 20 30 12
3 p123 25/02/2018 26/03/2018 10 10 13
df.dateeffe=pd.to_datetime(df.dateeffe)
df.date_fin=pd.to_datetime(df.date_fin)
df=df.sort_values(['id_police','dateeffe','date_fin'])
Комментарии:
1. что, если у меня будет 30 столбцов вместо одного дополнительного столбца? вот почему я использовал extra …. спасибо за ваш ответ и время…
2. Но подождите, даты не отсортированы… Пожалуйста, обновите:-(
3. Проблема в том, что мне нужно сортировать внутри каждого
id_police
, потому что некоторые id_police в базе данных имеют одинаковые интервалы… Итак, я должен отсортировать предложение groupby… Я уверен, что это возможно.. спасибо!4. @SabiriS. df=df.sort_values([‘id_police’,’dateeffe’,’date_fin’])
5. Не используйте apply с двумя группами, поскольку это замедлит весь процесс. Если у вас большой фрейм данных, примените лямбда x: x.groupby займет путь к длинному кодированию @SabiriS.happy
Ответ №2:
Я придумал решение, основанное на двухэтапном groupby.
Чтобы упростить сортировку по датам groupby
, давайте начнем с изменения типа обеих дат на datetime
:
df.dateeffe = pd.to_datetime(df.dateeffe)
df.date_fin = pd.to_datetime(df.date_fin)
Вторая часть представляет собой копию решения Wen-Ben для создания словаря
функций агрегирования (разумное решение, нет необходимости делать это каким-либо другим способом):
d = {'prime': 'max', 'prime2': 'max'}
d1 = dict.fromkeys(df.columns.difference(
['id_police', 'dateeffe', 'date_fin', 'prime', 'prime2']), 'first')
d.update(d1)
Затем давайте определим функцию, содержащую второй шаг groupby
, применяя
вышеуказанные функции агрегирования:
def fn(xx):
return xx.groupby(['dateeffe', 'date_fin'], as_index=False).agg(d)
И единственное, что нужно сделать, это фактическое вычисление, то есть первый шаг groupby
,
применяющий второй шаг groupby
, определенный выше:
df.groupby('id_police', sort=False).apply(fn)
.reset_index(level=1, drop=True).reset_index()
Обратите внимание на разницу между обоими groupby
случаями:
- Первый шаг
groupby
содержитsort=False
, поэтому сохраняется исходный порядокid_police
. - Но второй шаг
groupby
не имеетsort
аргумента, поэтому эта группировка выполняет сортировку по обеим датам.
И немного объяснений относительно обоих вызовов reset_index
:
df.groupby('id_police', sort=False).apply(fn)
создает фрейм данных со следующим мультииндексом:
id_police
p123 0
1
2
b123 0
Итак, первый reset_index
полностью удаляет уровень 1 (0, 1, 2, 0)
( drop=True
).
Но второй reset_index
фактически изменяет единственный оставшийся уровень индекса (p123, p123, p123, b123) в обычный столбец и создает индекс по умолчанию (последовательные числа от 0).
Комментарии:
1. Спасибо за ваш ответ, мне больше нравится ваш ответ, потому что это то, что я хотел, два groupby вместо одного. Еще раз спасибо!