Python根据每个列表的第一个值按自定义顺序排列列表
我想根据每个列表的第一个值按自定义顺序对列表列表进行排序。列表列表是pivot_表数据帧的我的列(Python根据每个列表的第一个值按自定义顺序排列列表,python,python-3.x,list,sorting,Python,Python 3.x,List,Sorting,我想根据每个列表的第一个值按自定义顺序对列表列表进行排序。列表列表是pivot_表数据帧的我的列(cols=list(dfOverview.columns.values)),其中一些列本身就是一个列表 最简单的工作示例(我希望以b开头的列在c之前移动): 这会返回一个错误,尽管我尝试了很多次并在谷歌上搜索了很多次,但我找不到一种方法来让它工作。cols的预期结果: ['2016', '2017', '2018', ('a', '2016'), ('a', '2017'), ('a',
cols=list(dfOverview.columns.values)
),其中一些列本身就是一个列表
最简单的工作示例(我希望以b
开头的列在c
之前移动):
这会返回一个错误,尽管我尝试了很多次并在谷歌上搜索了很多次,但我找不到一种方法来让它工作。cols的预期结果:
['2016', '2017', '2018',
('a', '2016'),
('a', '2017'),
('a', '2018'),
('b', '2016'),
('b', '2017'),
('c', '2016'),
('c', '2017'),
('c', '2018')]
为了澄清,我的问题的一些背景是:我对一个pandas数据框进行了数据透视,从而产生了一个新的数据框,其中的列可以由一系列值组成(以多列作为参数的透视表)。这使得订购变得困难,因此出现了上述问题
My dataframe是以下功能的结果:
dfPivot = df.pivot_table(index=['col1', 'col2'],
columns=['year','category'],
values='price')
问题源于您正在使用
键
。用于指定要比较的值的。您有一个异构列表。最后将比较不同类型的元素。我建议您看看cpm
参数,它是一个比较两个元素的函数。这样,您可以更精确地使用排序规则
如果我正确理解了您的问题,您很可能需要这种类型:
def compare(a, b):
if isinstance(a, str) and isinstance(b, str):
return cmp(a, b)
elif isinstance(a, str) and isinstance(b, tuple):
return cmp(a, b[1])
elif isinstance(b, str) and isinstance(a, tuple):
return cmp(a[1], b)
elif isinstance(a, tuple) and isinstance(b, tuple):
return cmp(a[1], b[1])
else:
print "Impossible"
return 0
cols.sort(cmp=compare)
print cols
查看列表输入时,有4种情况需要区分。字符串
案例、字符串元组
、元组字符串
和元组
案例
我们对每种情况进行说明,并为每种情况编写比较规则
在return
语句中使用的cmp
函数只是通知术语之间的关系,-1
为a
,0
为a=b
,1
为a>b
请注意,比较是字典式的(字符串比较)。您可能希望将字符串大小写为整数,并比较它们
结果是:
['2016', ('a', '2016'), ('c', '2016'), ('b', '2016'), '2017', ('a', '2017'), ('c', '2017'), ('b', '2017'), '2018', ('a', '2018'), ('c', '2018')]
如果将访问元组的第二个元素(本例中的年份)替换为访问第一个元素,您将得到以下结果:
['2016', '2017', '2018', ('a', '2016'), ('a', '2017'), ('a', '2018'), ('b', '2016'), ('b', '2017'), ('c', '2016'), ('c', '2017'), ('c', '2018')]
您可以添加一个标志来决定比较应该使用元组的哪一项。这将起作用。它将sort
key
设置为元组的第一个元素,或者将变量本身设置为其他元素
cols = ['2016', '2017', '2018',
('a', '2016'),
('a', '2017'),
('a', '2018'),
('c', '2016'),
('c', '2017'),
('c', '2018'),
('b', '2016'),
('b', '2017')]
sorted(cols, key=lambda k: k[0] if isinstance(k, tuple) else k)
# ['2016',
# '2017',
# '2018',
# ('a', '2016'),
# ('a', '2017'),
# ('a', '2018'),
# ('b', '2016'),
# ('b', '2017'),
# ('c', '2016'),
# ('c', '2017'),
# ('c', '2018')]
这样做有点老套,但你的方法也是老套的:D
>>> sorted(cols, key=lambda val: sortOrder[val[0]] if type(val) == tuple else sortOrder[val])
['2016', '2017', '2018', ('a', '2016'), ('a', '2017'), ('a', '2018'), ('b', '2016'), ('b', '2017'), ('c', '2016'), ('c', '2017'), ('c', '2018')]
谢谢!这是按字母顺序排序的,对吗?如何按自定义顺序对其进行排序(假设a之前是c)?您可以使用
reverse=True
参数,尽管我不确定这是否正是您想要的。最后,我想对数据帧的列进行重新排序,但由于我的dataframe是一个数据透视表,其中一些列名是一个列表而不是一个字符串。如果您需要其他订单,请随时更新问题&我可以更新答案。
>>> sorted(cols, key=lambda val: sortOrder[val[0]] if type(val) == tuple else sortOrder[val])
['2016', '2017', '2018', ('a', '2016'), ('a', '2017'), ('a', '2018'), ('b', '2016'), ('b', '2017'), ('c', '2016'), ('c', '2017'), ('c', '2018')]