按组合多列的条件对数据框进行排序

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

我有两个高级排序场景。

它们是独立的案例,因此我在下面列出了具有预期结果的示例。

import pandas as pd

a={
  "ip":['10.10.11.30','10.10.11.30','10.10.11.30', '10.2.2.10', '10.10.2.1', '10.2.2.2'],
  "path":['/data/foo/err','/data/foo/zone','/data/foo/err','/data/foo/zone','/data/foo/zone','/data/foo/tmp'],
  "date":['25/01/2024','25/01/2024','01/08/2020','23/01/2024','24/01/2024','25/01/2024'],
  "count":[3,10,20,5,20,50]
}
df=pd.DataFrame(a)

print(df)
print()

## Output
            ip            path         date  count
0  10.10.11.30   /data/foo/err   25/01/2024      3
1  10.10.11.30  /data/foo/zone   25/01/2024     10
2  10.10.11.30   /data/foo/err   01/08/2020     20
3    10.2.2.10  /data/foo/zone   23/01/2024      5
4    10.10.2.1  /data/foo/zone   24/01/2024     20
5     10.2.2.2   /data/foo/tmp   25/01/2024     50

可运行示例:https://onecompiler.com/python/422hhyqa5

排序案例1

规则

  • 按 ip ASC、日期 ASC、计数 ASC 排序

预期产量

            ip            path         date  count
5     10.2.2.2   /data/foo/tmp   25/01/2024     50
3    10.2.2.10  /data/foo/zone   23/01/2024      5
4    10.10.2.1  /data/foo/zone   24/01/2024     20
2  10.10.11.30   /data/foo/err   01/08/2020     20
0  10.10.11.30   /data/foo/err   25/01/2024      3
1  10.10.11.30  /data/foo/zone   25/01/2024     10

我的尝试

对多列执行“自然”排序非常简单(日期为 DateTime 类型)。

我还成功实现了按ip排序

但是我没能将两者结合起来,因为它总是给出不同的错误

df_sorted_by_date = (df.sort_values(by=['date', 'count'],
                    ascending=[True, True],
                    ignore_index=True)
df_sorted_by_ip = (df.sort_values(by=["ip"], 
                     key=lambda x: x.str.split(".").apply(lambda y: [int(z) for z in y]),
                     ignore_index=True))

排序案例2

规则

  • rank1
    :如果
    (path contains 'zone') and (count >=10)
    则排名第一并按
    IP ASC
  • 订购
  • rank2
    :如果
    (path NOT contains 'zone') and (count >=10) and (date = today())
    则排名第二并按
    IP ASC
  • 订购
  • rank3
    :剩余的行放在最后,并按
    IP ASC
    排序,然后按
    date ASC
    (如果值相等)

预期产量

假设今天是 25 号

            ip            path         date  count
4    10.10.2.1  /data/foo/zone   24/01/2024     20   # rank1
1  10.10.11.30  /data/foo/zone   25/01/2024     10   # rank1
5     10.2.2.2   /data/foo/tmp   25/01/2024     50   # rank2
3    10.2.2.10  /data/foo/zone   23/01/2024      5   # rank3
2  10.10.11.30   /data/foo/err   01/08/2020     20   # rank3
0  10.10.11.30   /data/foo/err   25/01/2024      3   # rank3

我的尝试

没有。我不知道如何继续,这对我来说非常先进>_<

python python-3.x pandas dataframe sorting
1个回答
0
投票

分配使用

numpy.select
计算的排名并使用
natsort
执行自然排序:

from natsort import natsort_key

df['date'] = pd.to_datetime(df['date'], dayfirst=True)
m1 = df['path'].str.contains('zone')
m2 = df['count'].ge(10)
m3 = df['date'].eq(pd.Timestamp('25/01/2024'))

df['rank'] = np.select([m1&m2, m2&m3&~m1],
                       ['rank1', 'rank2'],
                       'rank3')

out = df.sort_values(by=['rank', 'ip', 'date', 'count'], key=natsort_key)

输出:

            ip            path       date  count   rank
4    10.10.2.1  /data/foo/zone 2024-01-24     20  rank1
1  10.10.11.30  /data/foo/zone 2024-01-25     10  rank1
5     10.2.2.2   /data/foo/tmp 2024-01-25     50  rank2
3    10.2.2.10  /data/foo/zone 2024-01-23      5  rank3
2  10.10.11.30   /data/foo/err 2020-08-01     20  rank3
0  10.10.11.30   /data/foo/err 2024-01-25      3  rank3
© www.soinside.com 2019 - 2024. All rights reserved.