Pandas DataFrame多列组合条件排序的两种进阶场景求解
Pandas DataFrame两种进阶排序场景解决方案
示例数据
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)
排序场景1
排序规则
按ip升序、date升序、count升序排列
预期输出
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
解决方案
先将date列转换为datetime类型,在sort_values中为ip列指定自定义排序key,同时按多列顺序排序:
import pandas as pd # 转换date列为datetime类型,确保时间排序逻辑正确 df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y') # 多列组合排序 df_sorted = df.sort_values( by=['ip', 'date', 'count'], ascending=[True, True, True], key=lambda x: x.str.split('.').apply(lambda y: [int(z) for z in y]) if x.name == 'ip' else x, ignore_index=True ) print(df_sorted)
关键逻辑:仅对ip列按分段整数实现自然排序,date和count列使用默认排序逻辑,一次完成多列组合排序。
排序场景2
排序规则
- rank1:若
(path包含'zone')且(count >=10),列为第一优先级,按IP升序排列 - rank2:若
(path不包含'zone')且(count >=10)且(date=今日),列为第二优先级,按IP升序排列 - rank3:剩余行列为最后优先级,按IP升序排列,IP相同时按date升序排列
预期输出(假设今日为2024-01-25)
ip path date count 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
解决方案
先创建优先级rank列,再结合IP和日期的排序逻辑实现多条件排序:
import pandas as pd import numpy as np # 转换date列为datetime类型 df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y') # 定义今日日期(可替换为pd.Timestamp.today().normalize()获取当前系统日期) today = pd.Timestamp('2024-01-25') # 生成优先级rank列 conditions = [ (df['path'].str.contains('zone')) & (df['count'] >= 10), (~df['path'].str.contains('zone')) & (df['count'] >= 10) & (df['date'] == today) ] choices = [1, 2] df['rank'] = np.select(conditions, choices, default=3) # 按优先级、IP、日期排序 df_sorted = df.sort_values( by=['rank', 'ip', 'date'], ascending=[True, True, True], key=lambda x: x.str.split('.').apply(lambda y: [int(z) for z in y]) if x.name == 'ip' else x, ignore_index=True ).drop('rank', axis=1) # 移除临时rank列 print(df_sorted)
核心逻辑:通过np.select生成优先级标识,按rank升序实现优先级排序,再结合IP自然排序和日期排序完成最终排序。
内容的提问来源于stack exchange,提问作者Enissay
相关产品推荐
相关产品推荐

