赞
踩
工作中经常遇到需要根据某一个变量进行自定义排序,例如要排序长度字段["0-12","12-30","30-60","60-120","120-180","180-240","240-300","300+"]
,而这种又不可能直接用sort_value()
函数直接实现
使用pandas的CategoricalDtype
,将无序的字段转化为自定义的顺序。
然后将DataFrame中的相应字段用astype强制转化为这一种新建立的CategoricalDtype
。
注意:这个方法一定要让orderLIst的字段与目标表格的values相对应,不然不在orderList里的values会被astype
变成nan
import pandas as pd from pandas.api.types import CategoricalDtype def genOrder(df,orderList,colName): ''' 按自定排序函数 orderList最好是穷尽df[colName]的values Args: df: 要排序的目标表格 orderList: 顺序,e.g. ["0-12","12-30","30-60","60-120","120-180","180-240","240-300","300+"] colName: 顺序列的名称 e.g. 'explore_locale' Return: df: 将原有的colName变为有序,可以直接进行排序 ''' # 1. 建立新的有序类型 cat_order = CategoricalDtype(orderList,ordered=True) # 2. 将目标字段转化为该有序类型 df[colName] = df[colName].astype(cat_order) return df
建立一个测试表
test = pd.DataFrame({'a':['a','c','b'],'b':[1,'b',2]})
print(test)
print(test.info())
output:
a b
0 a 1
1 c b
2 b 2
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 a 3 non-null object
1 b 3 non-null object
dtypes: object(2)
注意到这里字段的Dtype都是object
然后使用自建函数进行转换
test = genOrder(test,['a','b','c'],'a')
test = genOrder(test,[1,2,'b'],'b')
print(test)
print(test.info())
可以发现结果中字段转变为category,就可以直接使用sort_values()
函数排序了。
a b
0 a 1
2 b 2
1 c b
<class 'pandas.core.frame.DataFrame'>
Int64Index: 3 entries, 0 to 1
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 a 3 non-null category
1 b 3 non-null category
dtypes: category(2)
这是之前一直在使用的一个比较笨的方法
就是建立一个新的DataFrame,包含两个字段一个字段为要排序的字段["0-12","12-30","30-60","60-120","120-180","180-240","240-300","300+"]
,另一个为数字字段[1,2,3,4,5,6,7]
将这个新的DataFrame与目标表格merge
之后就可以根据数字字段排序了。
这个方法思路很直观,但是不是特别推荐,因为一旦column是multipluIndex的时候就会出错。
def genOrder(df,orderList,colName): ''' 自定义排序函数 Args: df: 要排序的目标表格 orderList: 顺序,e.g. ['br', 'spa', 'in', 'pak', 'egy', 'tur'] colName: 顺序列的名称 e.g. 'explore_locale' Return: df: 在原有的dataFrame上增加新的一列名称为{}rank,并且按照这一列排序 ''' orderDf = pd.DataFrame({ '{}rank'.format(colName):[i for i in range(len(orderList))], colName:orderList }) tmpdf = orderDf.merge(df,on=colName).sort_values('{}rank'.format(colName)) return tmpdf
import pandas as pd from pandas.api.types import CategoricalDtype # def genOrder(df,orderList,colName): # ''' # 自定义排序函数 # Args: # df: 要排序的目标表格 # orderList: 顺序,e.g. ['br', 'spa', 'in', 'pak', 'egy', 'tur'] # colName: 顺序列的名称 e.g. 'explore_locale' # Return: # df: 在原有的dataFrame上增加新的一列名称为{}rank,并且按照这一列排序 # ''' # orderDf = pd.DataFrame({ # '{}rank'.format(colName):[i for i in range(len(orderList))], # colName:orderList # }) # tmpdf = orderDf.merge(df,on=colName).sort_values('{}rank'.format(colName)) # return tmpdf def genOrder(df,orderList,colName): ''' 按自定排序函数 orderList最好是穷尽df[colName]的values Args: df: 要排序的目标表格 orderList: 顺序,e.g. ['br', 'spa', 'in', 'pak', 'egy', 'tur'] colName: 顺序列的名称 e.g. 'explore_locale' Return: df: 将原有的colName变为有序,可以直接进行排序 ''' cat_order = CategoricalDtype(orderList,ordered=True) df[colName] = df[colName].astype(cat_order) return df if __name__ == '__main__': # 测试genOrder test = pd.DataFrame({'a':['a','c','b'],'b':[1,'b',2]}) print(test) test = genOrder(test,['a','b','c'],'a').sort_values('a') test = genOrder(test,[1,2,'b'],'b') print(test) print(test.info())
reference
dataframe 排序_如何对Pandas DataFrame进行自定义排序
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。