我有以下数据框:
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']
只是
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()]
从 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
时,最好的方法可能会有所不同。
要在字符串列表上获取自定义排序顺序,请将其声明为分类并手动指定排序顺序:
player_order = pd.Categorical([ 'Maurice Baker', 'Adrian Caldwell','Ratko Varda' ,'Ryan Bowen' ,'Cedric Hunter'],
ordered=True)
这是因为 pandas 还不允许分类作为索引:
df.set_index(keys=player_order, inplace=True)
TypeError: unhashable type: 'Categorical'
因此您需要使用
df.sort_index(level=player_order)
进行手动自定义排序
如果需要排序的列不止一列,根据我的经验,我会使用
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)
要按任意顺序排序而不包含空白行,我发现
df.filter
在测试 BENYS 答案 时可以工作。它根据需要进行排序,忽略丢失的键,例如 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