pandas 设置自定义排序(第一个和最后一个),而不知道所有值

5rgfhyps  于 2023-05-21  发布在  其他
关注(0)|答案(3)|浏览(210)

我有一个pandas DataFrame,其中包含以下信息

id          desc ammount
356 89 2521 ShouldBeFirst    0.00
356 89 2521  ShouldBeLast   19.00
356 89 2521   RandomValue   39.00
356 89 2521  RandomValue2   29.00
123 45 6789  RandomValue3   29.99
123 45 6789 ShouldBeFirst    0.00
123 45 6789  ShouldBeLast   99.00
123 45 6789  RandomValue3   39.00
123 45 6789  RandomValue2   19.00

我想要的是根据ID对DataFrame进行排序(这可以很容易地用df.sort_values('id', ascending=True)完成),然后将该ID的第一行始终设置为ShouldBeFirst,最后一行设置为ShouldBeLast,如下所示:

id          desc ammount
123 45 6789 ShouldBeFirst    0.00
123 45 6789  RandomValue2   19.00
123 45 6789  RandomValue3   29.99
123 45 6789  RandomValue3   39.00
123 45 6789  ShouldBeLast   99.00
356 89 2521 ShouldBeFirst    0.00
356 89 2521  RandomValue2   29.00
356 89 2521   RandomValue   39.00
356 89 2521  ShouldBeLast   19.00

我已经看到了几个关于如何自定义pandas DataFrame排序的线程,但它们都需要列出所有可能的值。我没有desc列上的所有值。

r3i60tvu

r3i60tvu1#

通过将已知值Map到预定义顺序来创建中间desc_order列,然后对 Dataframe 进行排序

df['desc_order'] = df['desc'].map({'ShouldBeFirst': 0, 'ShouldBeLast': 2}).fillna(1)
df.sort_values(['id', 'desc_order', 'ammount']).drop(columns=['desc_order'])
id           desc  ammount
5  123 45 6789  ShouldBeFirst     0.00
8  123 45 6789   RandomValue2    19.00
4  123 45 6789   RandomValue3    29.99
7  123 45 6789   RandomValue3    39.00
6  123 45 6789   ShouldBeLast    99.00
0  356 89 2521  ShouldBeFirst     0.00
3  356 89 2521   RandomValue2    29.00
2  356 89 2521    RandomValue    39.00
1  356 89 2521   ShouldBeLast    19.00
uxhixvfz

uxhixvfz2#

您可以使用自定义字典Map第一个和最后一个值,并将fillna用于其他值:

order = {'ShouldBeFirst': 0, 'ShouldBeLast': 2}

def sorter(s):
    if s.name == 'desc':
        return s.map(order).fillna(1)
    else:
        return s

out = df.sort_values(by=['id', 'desc', 'ammount'], key=sorter)

或者使用numpy.lexsort

order = {'ShouldBeFirst': 0, 'ShouldBeLast': 2}

df.iloc[np.lexsort([df['ammount'], df['desc'].map(order).fillna(1), df['id']])]

输出:

id           desc  ammount
5  123 45 6789  ShouldBeFirst     0.00
8  123 45 6789   RandomValue2    19.00
4  123 45 6789   RandomValue3    29.99
7  123 45 6789   RandomValue3    39.00
6  123 45 6789   ShouldBeLast    99.00
0  356 89 2521  ShouldBeFirst     0.00
3  356 89 2521   RandomValue2    29.00
2  356 89 2521    RandomValue    39.00
1  356 89 2521   ShouldBeLast    19.00
sd2nnvve

sd2nnvve3#

从这个开始......
将pandas导入为pd

# Assuming the DataFrame is already available as 'df'
df_sorted = df.sort_values('id', ascending=True)

mask = df_sorted.duplicated('id', keep=False)
df_sorted.loc[mask, 'order'] = 1
df_sorted.loc[~mask, 'order'] = [0, 2] * (df_sorted['id'].nunique() // 2 + 1)

df_sorted = df_sorted.sort_values(['id', 'order']).drop('order', axis=1)

print(df_sorted)

相关问题