提问人:skeetastax 提问时间:11/8/2023 更新时间:11/8/2023 访问量:61
如何在 Python 中按多列对二维数组进行排序?
How do I sort a 2D array in Python by multiple columns?
问:
我有一个二维(2D)Python数组(数组数组):
arr = [[130, 175, 75, 152],
[96, 132, 122, 112],
[174, 218, 141, 196],
[661, 701, 21, 683],
[707, 746, 375, 724],
[957, 998, 305, 980],
[768, 806, 26, 788],
[957, 998, 394, 974],
[768, 806, 286, 787],
[174, 218, 328, 194],
[894, 933, 80, 914],
[130, 175, 182, 152],
[96, 132, 329, 114],
[894, 933, 166, 913]]
我想先按第 1 列分层排序,然后按第 2 列排序,然后按第 3 列排序,就像 Excel 中的数据透视表或多列排序一样。
结果应为:
[[96, 132, 122, 112],
[96, 132, 329, 114],
[130, 175, 75, 152],
[130, 175, 182, 152],
[174, 218, 141, 196],
[174, 218, 328, 194],
[661, 701, 21, 683],
[707, 746, 375, 724],
[768, 806, 26, 788],
[768, 806, 286, 787],
[894, 933, 80, 914],
[894, 933, 166, 913],
[957, 998, 305, 980],
[957, 998, 394, 974]]
我曾经使用过,但我不确定下面发生了什么,并且想要一些更具确定性的东西。arr.sort()
- 我该如何以数字方式(而不是词典方式)做到这一点?
- 我将如何在任何列组合上做到这一点(在一般意义上)?
答:
1赞
matszwecja
11/8/2023
#1
Python 已经对数字进行了排序。如果要按字典排序,则需要将数字转换为字符串。
按多列排序的最简单方法是利用 Python 保证排序稳定的事实 - 这意味着元素的顺序保持不变,以防它们在排序键方面捆绑在一起。 使用它,你可以从最低有效键到最高有效键进行排序,从而产生预期的输出:
res = sorted(
sorted(
sorted(
sorted(arr, key = lambda x: x[3]),
key = lambda x: x[2]),
key = lambda x: x[1]),
key = lambda x: x[0])
输出:
[96, 132, 122, 112]
[96, 132, 329, 114]
[130, 175, 75, 152]
[130, 175, 182, 152]
[174, 218, 141, 196]
[174, 218, 328, 194]
[661, 701, 21, 683]
[707, 746, 375, 724]
[768, 806, 26, 788]
[768, 806, 286, 787]
[894, 933, 80, 914]
[894, 933, 166, 913]
[957, 998, 305, 980]
[957, 998, 394, 974]
评论
0赞
Stef
11/8/2023
我不喜欢这个答案有两个原因。(1)它无用的复杂。 将产生完全相同的结果;无需使用自定义 Lambda 键进行四次排序。(2)你最后的评论是错误的。默认情况下,两者都按字典顺序排序,这就是为什么在 .res = sorted(arr)
list.sort
sorted
[96, 132, 122, ...]
[96, 132, 329, ...]
0赞
matszwecja
11/8/2023
@Stef (2) 我不确定这如何证明任何事情都是按词典排序的。字典排序与数字排序的示例可以用 - 输出是 。您的示例将以相同的方式排序,无论是词法排序还是数字排序。print(sorted(["96", "123"])); print(sorted([96, 123]))
['123', '96']; [96, 123]
0赞
matszwecja
11/8/2023
@Stef (1) 这种情况是正确的,但如果用于排序的列顺序不同(例如 (1->4->2->3)),如果排序时应忽略某些列等,则对更复杂的事情无济于事。
0赞
Stef
11/8/2023
即使对于更复杂的事情,也有比排序四次更好的解决方案。您可以进行一次排序,并指定一个键来指示如何使用 lambda 或 itemgetter 进行排序。至于你对词典排序的评论,我不明白。如果你正在寻找一个“证明”,我建议你阅读 和 的文档,或者阅读他们在 CPython 实现中的代码,或者做一些实验。list.sort
sorted
1赞
skeetastax
11/8/2023
我认为可以公平地说,花费大量时间并撰写大量论文讨论各种排序算法及其好处是有充分理由的。人们可以合理地争辩说,仅两个离散值的简单比较就是一种排序操作。对仅包含 3 个元素的列表进行排序必然需要 3 次比较。@Stef,是的,对于简单的表格排序,可能没问题,但我也要求更通用的方法,可以应用于许多不同的排序要求,我感谢@matszwecja的通用解决方案。.sort()
-1赞
Willy Lutz
11/8/2023
#2
使用 argsort
:
arr = np.array([[130, 175, 75, 152],
[96, 132, 122, 112],
[174, 218, 141, 196],
[661, 701, 21, 683],
[707, 746, 375, 724],
[957, 998, 305, 980],
[768, 806, 26, 788],
[957, 998, 394, 974],
[768, 806, 286, 787],
[174, 218, 328, 194],
[894, 933, 80, 914],
[130, 175, 182, 152],
[96, 132, 329, 114],
[894, 933, 166, 913]])
sorted_arr = arr[arr[:, 0].argsort()]
print(sorted_arr)
输出你想要的东西。
简短的解释(更多细节在这里)是获取数组列的排序索引,然后使用结果作为行索引并将结果数组分配回 a,如下所示。argsort()
argsort
如果你想(如你的第二点?)根据第二列对它进行排序,在你的列中使用或设定优先级,在提到的链接中查看你应该找到你想要的东西。sorted_arr = arr[arr[:, 1].argsort()]
评论
arr.sort()
arr.sort()
arr.sort()
arr.sort()