您可以使用口罩和numpy.lexsort
:
import numpy as np
m = df['trigger'].isin(df.index)
key = df['trigger'].where(m, df.index)
out = df.iloc[np.lexsort([m, key])]
或者是纯Pandas (不那么优雅的IMO,但如果你需要定制订单,则更灵活;见下文):
out = (df
.assign(m=df['trigger'].isin(df.index),
key=lambda d: d['trigger'].where(m, d.index))
.sort_values(by=['key', 'm'])
.drop(columns=['m', 'key'])
)
输出:
trigger command
key1 cron1 command1
key2 key1 command2
key3 cron3 command3
key4 key3 command4
key5 cron5 command5
中间体:
# before sorting
trigger command m key
key4 key3 command4 True key3
key2 key1 command2 True key1
key3 cron3 command3 False key3
key5 cron5 command5 False key5
key1 cron1 command1 False key1
# after sorting
trigger command m key
key1 cron1 command1 False key1
key2 key1 command2 True key1
key3 cron3 command3 False key3
key4 key3 command4 True key3
key5 cron5 command5 False key5
如果要保持组的原始顺序(key3 -> key5 -> key1
):
out = (df
.assign(m=df['trigger'].isin(df.index),
key=lambda d: pd.Categorical(d['trigger'].where(m, d.index),
categories=d.index[~d['m']].unique(),
ordered=True)
)
.sort_values(by=['key', 'm'])
.drop(columns=['m', 'key'])
)
变体:
m = df['trigger'].isin(df.index)
key = df['trigger'].where(m, df.index)
order = df.index[~m].unique()
tmp = df.assign(key=pd.Categorical(key, categories=order, ordered=True))
out = (pd.concat([tmp[~m], tmp[m]]).sort_values(by='key', kind='stable')
.drop(columns='key')
)
输出:
trigger command
key3 cron3 command3
key4 key3 command4
key5 cron5 command5
key1 cron1 command1
key2 key1 command2