提问人:littleworth 提问时间:4/25/2018 最后编辑:Peter Mortensenlittleworth 更新时间:9/16/2023 访问量:43283
如何按字符串索引的自定义顺序对 pandas 数据帧进行排序
How to sort a pandas dataframe by a custom order on a string index
问:
我有以下数据帧:
import pandas as pd
df = pd.DataFrame({'id': [2967, 5335, 13950, 6141, 6169],
'Player': ['Cedric Hunter', 'Maurice Baker',
'Ratko Varda', 'Ryan Bowen', 'Adrian Caldwell'],
'Year': [1991, 2004, 2001, 2009, 1997],
'Age': [27, 25, 22, 34, 31],
'Tm': ['CHH', 'VAN', 'TOT', 'OKC', 'DAL'],
'G': [6, 7, 60, 52, 81]})
df.set_index('Player', inplace=True)
它显示:
Out[128]:
Age G Tm Year id
Player
Cedric Hunter 27 6 CHH 1991 2967
Maurice Baker 25 7 VAN 2004 5335
Ratko Varda 22 60 TOT 2001 13950
Ryan Bowen 34 52 OKC 2009 6141
Adrian Caldwell 31 81 DAL 1997 6169
如何使用任意顺序按索引(“玩家”)排序?例如,如下图所示。
reorderlist = ['Maurice Baker',
'Adrian Caldwell',
'Ratko Varda',
'Ryan Bowen',
'Cedric Hunter']
答:
4赞
smci
4/25/2018
#1
若要获取字符串列表的自定义排序顺序,请将其声明为分类,并在排序中手动指定该顺序:
player_order = pd.Categorical([ 'Maurice Baker', 'Adrian Caldwell','Ratko Varda' ,'Ryan Bowen' ,'Cedric Hunter'],
ordered=True)
这是因为 pandas 还不允许 Categoricals 作为索引:df.set_index(keys=player_order, inplace=True)
TypeError: unhashable type: 'Categorical'
因此,您需要使用df.sort_index(level=player_order)
评论
0赞
jean-loup
12/27/2018
请给出一个解决方案,而不是“......”点
1赞
smci
12/29/2018
@jean-loup:我已经在这里给出了解决方案,但要 200% 清楚:df.sort_index(level=player_order)
57赞
BENY
4/25/2018
#2
只reindex
df.reindex(reorderlist)
Out[89]:
Age G Tm Year id
Player
Maurice Baker 25 7 VAN 2004 5335
Adrian Caldwell 31 81 DAL 1997 6169
Ratko Varda 22 60 TOT 2001 13950
Ryan Bowen 34 52 OKC 2009 6141
Cedric Hunter 27 6 CHH 1991 2967
更新信息,您有多个同名玩家
out = df.iloc[pd.Categorical(df.index,reorderlist).argsort()]
评论
1赞
tiru
9/24/2019
您好,我已经尝试过这个玩家正在作为记录器列表获得,但所有其他值都属于 NAN。我想要与上面完全相同的值
0赞
Diego F Medina
2/19/2022
当有同名的玩家时,这不起作用。
0赞
BENY
2/19/2022
@DiegoFMedina检查更新
11赞
totalhack
9/15/2020
#3
从 Pandas 1.1 开始,DataFrame.sort_values 有一个参数,它接受一个可调用对象来控制排序。因此,您可以使用如下方法:key
def sorter(column):
reorder = [
"Maurice Baker",
"Adrian Caldwell",
"Ratko Varda",
"Ryan Bowen",
"Cedric Hunter",
]
# This also works:
# mapper = {name: order for order, name in enumerate(reorder)}
# return column.map(mapper)
cat = pd.Categorical(column, categories=reorder, ordered=True)
return pd.Series(cat)
df_sorted = df.sort_values(by="Player", key=sorter)
使用和我在评论中提出的替代方案之间可能存在一些实际差异。例如,请参阅这些注意事项。为了完整起见,我展示了两者。我也没有测试过这与当前公认的使用 .当您也参与其中时,最好的方法可能会有所不同。pd.Categorical
column.map
df.reindex
MultiIndex
评论
5赞
madprogramer
7/13/2021
不是所有的英雄都穿斗篷!显然,有些人戴着围巾!
0赞
T. Hall
4/3/2022
#4
在不包含空白行的情况下按任意顺序排序,我发现在测试 BENYS 答案时有效。它根据需要进行排序,忽略缺少的键,例如 ,但有助于不包含没有数据的键的空行。df.filter
df.reindex
df.filter(reorderlist, axis=0)
id Year Age Tm G
Player
Maurice Baker 5335 2004 25 VAN 7
Adrian Caldwell 6169 1997 31 DAL 81
Ratko Varda 13950 2001 22 TOT 60
Ryan Bowen 6141 2009 34 OKC 52
Cedric Hunter 2967 1991 27 CHH 6
#Extra keys dont add empty rows, missing keys ignored
reorderlist.append('LeBron James')
reorderlist.remove('Adrian Caldwell')
df.filter(reorderlist, axis=0)
id Year Age Tm G
Player
Maurice Baker 5335 2004 25 VAN 7
Ratko Varda 13950 2001 22 TOT 60
Ryan Bowen 6141 2009 34 OKC 52
Cedric Hunter 2967 1991 27 CHH 6
1赞
PTQuoc
5/27/2022
#5
如果有多个列需要排序,根据我的经验,我习惯于将值转换为 .然后使用:map
string
number
sort_values
# Step 1/3: create dictionary to convert any string to number
convert_dict = {'Maurice Baker':1,
'Adrian Caldwell':2,
'Ratko Varda':3} # You can start filling till the end
# Step 2/3: Create column `new` that mapping from `Player`:
df['new'] = df['Player'].map(convert_dict)
# Step 3/3: sort
df.sort_values(by=['new'], ignore_index=True, inplace=True)
df.drop(columns=['new'], inplace=True)
0赞
Keyub W
11/30/2023
#6
我发现的最简单的方法是将列表传递给 ,但如果索引不唯一,这将不起作用。.loc
df = df.loc[reorderlist, :]
评论
reorderlist