Pandas Sort - Проблемы в порядке - PullRequest
0 голосов
/ 04 ноября 2019

У меня есть df, как это,

    param       per     per_date    per_num             
0   XYZ         1.0     2018-10-01  11.0                
1   XYZ         2.0     2017-08-01  15.25               
2   XYZ         1.0     2019-10-01  11.25
3   XYZ         2.0     2019-08-01  15.71 
4   XYZ         3.0     2020-10-01  NaN 
5   MMG         1.0     2021-10-01  12.50                          
6   MMG         2.0     2021-10-01  11.75               
7   MMG         3.0     2011-01-01  NaN                
8   ZZZ         4.0     2023-01-01  19.00 
9   ZZZ         3.0     2014-01-01  13.00
10  MMM         1.0     2016-03-01  12.01
11  MMM         2.0     2019-01-01  16.00
12  ZZZ         1.0     2009-06-01  12.50
13  ZZZ         2.0     2018-01-01  19.00

Мне нужен отсортированный вывод, как это,

        param       per     per_date    per_num 
    0   MMG         1.0     2021-10-01  12.50                          
    1   MMG         2.0     2021-10-01  11.75               
    2   MMG         3.0     2011-01-01  NaN  
    3   MMM         1.0     2016-03-01  12.01
    4   MMM         2.0     2019-01-01  16.00
    5   XYZ         1.0     2018-10-01  11.0                
    6   XYZ         2.0     2017-08-01  15.25               
    7   XYZ         1.0     2019-10-01  11.25
    8   XYZ         2.0     2019-08-01  15.71 
    9   XYZ         3.0     2020-10-01  NaN 
    10  ZZZ         1.0     2009-06-01  12.50
    11  ZZZ         2.0     2018-01-01  19.00              
    12  ZZZ         4.0     2023-01-01  19.00 
    13  ZZZ         3.0     2014-01-01  13.00

Однако, когда я делаю сортировку,

df= df.sort_values(['param', 'per']).reset_index(drop=True)
df

Я получаю, (не то, что я хочу)

   param  per   per_date    per_num
0   MMG   1.0   2021-10-01  12.50
1   MMG   2.0   2021-10-01  11.75
2   MMG   3.0   2011-01-01  NaN
3   MMM   1.0   2016-03-01  12.01
4   MMM   2.0   2019-01-01  16.00
5   XYZ   1.0   2018-10-01  11.00
6   XYZ   1.0   2019-10-01  11.25
7   XYZ   2.0   2017-08-01  15.25
8   XYZ   2.0   2019-08-01  15.71
9   XYZ   3.0   2020-10-01  NaN
10  ZZZ   1.0   2009-06-01  12.50
11  ZZZ   2.0   2018-01-01  19.00
12  ZZZ   3.0   2014-01-01  13.00
13  ZZZ   4.0   2023-01-01  19.00

Если вы видите выше в оригинале df xyz имеет per значения 1,2, а затем начинается снова с 1,23 они две разные категории. Я хочу сохранить этот порядок как есть. Тем не менее, ZZZ все в одном порядке, так что одна категория ,, но порядок не тот и требует для этого заказа. Как я могу сделать это в пандах?

Цените любые предложения.

Ответы [ 4 ]

1 голос
/ 04 ноября 2019

Как насчет этого?

df.assign(sortkey=-df.groupby(['param','per']).cumcount()).sort_values(['param','sortkey','per']).reset_index(drop=True)
1 голос
/ 04 ноября 2019

Обновление:

df.assign(sortkey=df.groupby('param')
                    .apply(lambda x:x.duplicated(['param','per']).cumsum())
                    .reset_index(level=0, drop=True))\
  .sort_values(['param','sortkey','per'])

Вывод:

   param  per    per_date  per_num  sortkey
5    MMG  1.0  2021-10-01    12.50        0
6    MMG  2.0  2021-10-01    11.75        0
7    MMG  3.0  2011-01-01      NaN        0
10   MMM  1.0  2016-03-01    12.01        0
11   MMM  2.0  2019-01-01    16.00        0
0    XYZ  1.0  2018-10-01    11.00        0
1    XYZ  2.0  2017-08-01    15.25        0
2    XYZ  1.0  2019-10-01    11.25        1
3    XYZ  2.0  2019-08-01    15.71        2
4    XYZ  3.0  2020-10-01      NaN        2
12   ZZZ  1.0  2009-06-01    12.50        0
13   ZZZ  2.0  2018-01-01    19.00        0
9    ZZZ  3.0  2014-01-01    13.00        0
8    ZZZ  4.0  2023-01-01    19.00        0
1 голос
/ 04 ноября 2019

Мы можем использовать Categorical

df.param = pd.Categorical(df.param, categories = df.param.unique())
df = df.sort_values(['param', 'per']).reset_index(drop = True)
df
Out[348]: 
   param  per    per_date  per_num
0    XYZ  1.0  2018-10-01    11.00
1    XYZ  1.0  2019-10-01    11.25
2    XYZ  2.0  2017-08-01    15.25
3    XYZ  2.0  2019-08-01    15.71
4    XYZ  3.0  2020-10-01      NaN
5    MMG  1.0  2021-10-01    12.50
6    MMG  2.0  2021-10-01    11.75
7    MMG  3.0  2011-01-01      NaN
8    ZZZ  1.0  2009-06-01    12.50
9    ZZZ  2.0  2018-01-01    19.00
10   ZZZ  3.0  2014-01-01    13.00
11   ZZZ  4.0  2023-01-01    19.00
12   MMM  1.0  2016-03-01    12.01
13   MMM  2.0  2019-01-01    16.00

Обновление

df.param = pd.Categorical(df.param, categories = df.param.unique())

df['Key']=df.groupby(['param','per']).cumcount()
df = df.sort_values(['param','Key', 'per']).reset_index(drop = True).drop('Key',1)
df
Out[375]: 
   param  per    per_date  per_num
0    XYZ  1.0  2018-10-01    11.00
1    XYZ  2.0  2017-08-01    15.25
2    XYZ  3.0  2020-10-01      NaN
3    XYZ  1.0  2019-10-01    11.25
4    XYZ  2.0  2019-08-01    15.71
5    MMG  1.0  2021-10-01    12.50
6    MMG  2.0  2021-10-01    11.75
7    MMG  3.0  2011-01-01      NaN
8    ZZZ  1.0  2009-06-01    12.50
9    ZZZ  2.0  2018-01-01    19.00
10   ZZZ  3.0  2014-01-01    13.00
11   ZZZ  4.0  2023-01-01    19.00
12   MMM  1.0  2016-03-01    12.01
13   MMM  2.0  2019-01-01    16.00
0 голосов
/ 04 ноября 2019

вам нужно сгруппировать 1-ю группу по параметру и per и присвоить уникальное значение по одному групперу. Затем снова группируйте по параметрам и группировщикам и сортируйте каждую группу по параметрам и по

import pandas as pd
from pandas import Timestamp

df = pd.DataFrame([['XYZ', 1.0, Timestamp('2018-10-01 00:00:00'), 11.0], ['XYZ', 2.0, Timestamp('2017-08-01 00:00:00'), 15.25], ['XYZ', 1.0, Timestamp('2019-10-01 00:00:00'), 11.25], ['XYZ', 2.0, Timestamp('2019-08-01 00:00:00'), 15.71], ['MMG', 1.0, Timestamp('2021-10-01 00:00:00'), 12.5], ['MMG', 2.0, Timestamp('2021-10-01 00:00:00'), 11.75], ['ZZZ', 4.0, Timestamp('2023-01-01 00:00:00'), 19.0], ['ZZZ', 3.0, Timestamp('2014-01-01 00:00:00'), 13.0], ['MMM', 1.0, Timestamp('2016-03-01 00:00:00'), 12.01], ['MMM', 2.0, Timestamp('2019-01-01 00:00:00'), 16.0], ['ZZZ', 1.0, Timestamp('2009-06-01 00:00:00'), 12.5], ['ZZZ', 2.0, Timestamp('2018-01-01 00:00:00'), 19.0]], columns=('param', 'per', 'per_date', 'per_num'))

df["grouper"] = df.groupby(["param", "per"]).cumcount()

df.groupby(["param", "grouper"])\
.apply(lambda g: g.sort_values(["param", "per"]))\
.reset_index(drop=True)

Результат

param  per   per_date  per_num  grouper
0    MMG  1.0 2021-10-01    12.50        0
1    MMG  2.0 2021-10-01    11.75        0
2    MMM  1.0 2016-03-01    12.01        0
3    MMM  2.0 2019-01-01    16.00        0
4    XYZ  1.0 2018-10-01    11.00        0
5    XYZ  2.0 2017-08-01    15.25        0
6    XYZ  1.0 2019-10-01    11.25        1
7    XYZ  2.0 2019-08-01    15.71        1
8    ZZZ  1.0 2009-06-01    12.50        0
9    ZZZ  2.0 2018-01-01    19.00        0
10   ZZZ  3.0 2014-01-01    13.00        0
11   ZZZ  4.0 2023-01-01    19.00        0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...