Сортировка дат в фрейме данных в соответствии со столбцом с сохранением значений других столбцов с использованием Pandas

#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 вместо одного. Еще раз спасибо!