Python 结构化 numpy 数组多重排序



大家好,我有一个分隔符分隔字符串的列表:

lists=['1|Abra|23|43|0','2|Cadabra|15|18|0','3|Grabra|4|421|0','4|Lol|1|15|0']

我需要将其转换为 numpy 数组,而不是像 excel 一样先按第 3 列排序,然后按第 2 列排序,最后按最后一列进行排序我试过这个:

def man():
a = np.array(lists[0].split('|'))
for line in lists:
    temp = np.array(line.split('|'),)
    a=np.concatenate((a, temp))
a.sort(order=[0, 1])
man()

当然没有运气,因为它是错误的!不幸的是,我在 numpy 数组中并不强大。有人可以帮我吗?:(

这对我来说非常完美,但在这里 numpy 从文件构建数组,所以为了让它工作,我已经将我的字符串列表写入文件,而不是读取它并转换为数组

import numpy as np
# let numpy guess the type with dtype=None
my_data = np.genfromtxt('Selector/tmp.txt',delimiter='|', dtype=None, names ["Num", "Date", "Desc", "Rgh" ,"Prc", "Color", "Smb", "MType"])
my_data.sort(order=["Color","Prc", "Rgh"])
# save specifying required format (tab separated values)
print(my_data)

如何保持一切原样,但更改转换函数以使其不是从文件而是从列表中构建相同的数组

可能有更好的解决方案,但首先我会按每列以相反的顺序对数组进行一次排序。

我假设您要按第 3 列排序,并且由第 2 列解决关系。最后,剩余的连接由最后一列解析。因此,您实际上会先按最后一列排序,然后按 2 排序,然后按 3 排序。

此外,您可以使用列表推导式轻松地将列表转换为数组。

import numpy as np
lists=['1|Abra|23|43|0','2|Cadabra|15|18|0','3|Grabra|4|421|0','4|Lol|1|15|0']
# convert to numpy array by splitting each row
a = np.array([l.split('|') for l in lists])
# specify columns to sort by, in order
sort_cols = [3, 2, -1]
# sort by columns in reverse order.
# This only works correctly if the sorting algorithm is stable.
for sc in sort_cols[::-1]:
    order = np.argsort(a[:, sc])
    a = a[order]
print(a)

您可以使用列表推导来拆分字符串并将整数转换为int。然后使用适当的dtype来创建 numpy 数组,然后通过传递预期的顺序来使用np.sort()函数:

>>> dtype = [('1st', int), ('2nd', '|S7'), ('3rd', int), ('4th', int), ('5th', int)]
>>> 
>>> a = np.array([tuple([int(i) if i.isdigit() else i for i in sub.split('|')]) for sub in delimit_strs], dtype=dtype)
>>> np.sort(a, axis=0, order=['3rd','2nd', '5th'])
array([(4, 'Lol', 1, 15, 0), (3, 'Grabra', 4, 421, 0),
       (2, 'Cadabra', 15, 18, 0), (1, 'Abra', 23, 43, 0)], 
      dtype=[('1st', '<i8'), ('2nd', 'S7'), ('3rd', '<i8'), ('4th', '<i8'), ('5th', '<i8')])

你也可以在python中做到这一点,这对于更短的数据集更优化。您可以通过传递适当的键函数来简单地使用sorted()函数。

from operator import itemgetter
sorted([[int(i) if i.isdigit() else i for i in sub.split('|')]) for sub in delimit_strs], key=itemgetter(3, 2, 4))

最新更新