如何对多行部分中具有多个条件的多列进行 pandas 数据框排序?

问题描述 投票:0回答:1

问题如下,我有一个数据框

df
有多列
a,b,c,d

a
包含整数值;
b
包含的字符串可以是
LM
OM
Ref
None
c
包含浮点值;
d
包含字符串

我想对数据框进行排序,例如

  • 所有带有
    b=OM
    的行首先按
    c
  • 的升序排序
  • 所有带有
    b=LM
    的行都位于 OM 行之后,但按
    c
  • 的降序排列
  • 所有带有
    b=Ref
    的行按升序排列在 LM 行之后
    c
  • 所有带
    b=none
    的行都按升序排列在参考行之后
    c

或者,我想知道是否可以按 a 的特定顺序进行排序,例如,如果我有一个名为

a
S
值列表/数组,例如
S=[18,5,7,33]
,我可以订购数据框通过以下方式

  • 所有带有
    b=OM
    的行首先按
    c
  • 的升序排序
  • 所有带有
    b=LM
    的行都位于 OM 行之后,但按照
    S
    的元素顺序排序,例如带有
    a
    的行按照
    S
  • 的元素顺序排序
  • 所有带有
    b=Ref
    的行按升序排列在 LM 行之后
    c
  • 所有带
    b=none
    的行都按升序排列在参考行之后
    c

我将冒险假设解决方案类似于

  • df
    按每个 b 列值进行切片,以便获得我可以排序的子集,并沿着这些线
    df1 = df[(df['b'] == 'OM')
    冲洗并重复 4 次,以获得不同的
    b
    值(或循环查找列表中保存的所有类别)
  • 按照
    df
    的方式对每个
    df1 = df.sort_values(by=['c'], ascending=True)
    进行独立排序,其中升序
    True
    False
    用于每种情况,或者按列表进行更复杂的排序,应沿着
  • 的方式进行排序
df2.a = df2.a.astype("category")
df2.a = df2.a.cat.set_categories(S)
df2=df2.sort_values(["a"])
  • 然后按照
  • 的顺序连接数据帧
frames = [df1,df2,df3,df4]
result = pd.concat(frames)
result.reset_index()

为了以正确的顺序获得

df
的索引,因为我会为我得到的每个结果重复它们

  • 使用迭代器获取结果数据帧行并使用

所以问题是

  1. 这是解决问题的正确方法吗?或者我会做一些明显错误的事情,如果是这样,解决问题的“正确”方法是什么?
  2. 这里使用的按列表排序是最好的选择吗?
  3. 是否有一些我没有想到的潜在陷阱?

感谢任何人的指点。

python pandas dataframe sorting
1个回答
0
投票

您可以为每一行分配一个分数

k1 + k2
,该分数由两个因素组成:主要因素
k1
取决于
b
值,次要因素
k2
取决于
c
值。

如果

k1
['LM', 'OM', 'Ref', 'None'].index(b)
0 < k2 < 1
,则按此分数排序将具有按
b
排序,然后在相同值
c
的组内按
b
排序的效果。

要按

c
升序排序,我们可以使用
k2 = norm(c)
c
降序排序,我们可以使用
k2 = 1 - norm(c)
,其中
norm
c
从范围
cmin..cmax
转换为范围
0..1

import pandas as pd
import random
import numpy as np

N = 20

df = pd.DataFrame({
    "b": [random.choice(['LM', 'OM', 'Ref', 'None']) for i in range(N)],
    "c": np.random.uniform(-5, 5, N)
})

cmin = df.c.min()
cmax = df.c.max()
df['cnorm'] = (df.c - cmin) / (cmax - cmin)

df['score'] = np.where(df.b == 'OM', df.cnorm, 
                       np.where(df.b == 'LM', 2 - df.cnorm,
                                np.where(df.b == 'Ref', 2 + df.cnorm, 
                                         np.where(df.b == 'None', 3 + df.cnorm, 0))))

df.sort_values(by=['score'], inplace=True)
del df['score']
del df['cnorm']
print(df)
© www.soinside.com 2019 - 2024. All rights reserved.