Рассмотрим следующий код:
import pandas
import numpy
strs = ['custom','sort']*5
df = pandas.DataFrame(
{
'string': strs,
'number': numpy.random.randn(len(strs)),
}
)
sort_string_like_this = {'sort': 0, 'custom': 1}
print(df.sort_values(['string','number'], key=lambda x: x.map(sort_string_like_this)))
который печатает
string number
1 sort -0.074041
3 sort 1.057676
5 sort -0.612289
7 sort 0.757922
9 sort 0.671288
0 custom -0.339373
2 custom -0.320231
4 custom -1.125380
6 custom 2.120829
8 custom -0.031580
Я хотел бы отсортировать его по столбцу string
, используя индивидуальный порядок, заданный словарем, и по столбцу number
, используя естественный порядок чисел. Как это можно сделать?
🤔 А знаете ли вы, что...
Python подходит для начинающих программистов благодаря своей простоте и читаемости кода.
Вы можете использовать условие в функции ключа сортировки:
df.sort_values(
["string", "number"],
key=lambda x: x.map(sort_string_like_this) if x.name == "string" else x,
)
string number
7 sort -1.673626
3 sort -0.212634
5 sort -0.071417
9 sort 0.413497
1 sort 0.489508
8 custom -1.787110
0 custom 0.230875
4 custom 0.535791
2 custom 0.671282
6 custom 2.119993
ИМХО, самый простой подход — использовать numpy.lexsort:
import numpy as np
out = df.iloc[np.lexsort([df['number'], df['string'].map(sort_string_like_this)])]
Другой вариант со словарем:
sorter = {'string': lambda x: x.map(sort_string_like_this),
'number': lambda x: x
}
out = df.sort_values(by=['string', 'number'], key=lambda x: sorter.get(x.name)(x))
Выход:
string number
5 sort -0.612289
1 sort -0.074041
9 sort 0.671288
7 sort 0.757922
3 sort 1.057676
4 custom -1.125380
0 custom -0.339373
2 custom -0.320231
8 custom -0.031580
6 custom 2.120829