我正在尝试对第 1 列、第 2 列和第 3 列的以下数组进行排序
[['2008' '1' '23' 'AAPL' 'Buy' '100']
['2008' '1' '30' 'AAPL' 'Sell' '100']
['2008' '1' '23' 'GOOG' 'Buy' '100']
['2008' '1' '30' 'GOOG' 'Sell' '100']
['2008' '9' '8' 'GOOG' 'Buy' '100']
['2008' '9' '15' 'GOOG' 'Sell' '100']
['2008' '5' '1' 'XOM' 'Buy' '100']
['2008' '5' '8' 'XOM' 'Sell' '100']]
我使用了以下代码:
idx=np.lexsort((order_array[:,2],order_array[:,1],order_array[:,0]))
order_array=order_array[idx]
结果数组是
[['2008' '1' '23' 'AAPL' 'Buy' '100']
['2008' '1' '23' 'GOOG' 'Buy' '100']
['2008' '1' '30' 'AAPL' 'Sell' '100']
['2008' '1' '30' 'GOOG' 'Sell' '100']
['2008' '5' '1' 'XOM' 'Buy' '100']
['2008' '5' '8' 'XOM' 'Sell' '100']
['2008' '9' '15' 'GOOG' 'Sell' '100']
['2008' '9' '8' 'GOOG' 'Buy' '100']]
问题是最后两行是错误的。正确的数组应该将最后一行作为倒数第二行。我已经尝试了一切,但无法理解为什么会这样。将不胜感激。
我正在使用以下代码获取 order_array。
for i in ….
x= ldt_timestamps[i] # this is a list of timestamps
s_sym=……
list=[int(x.year),int(x.month),int(x.day),s_sym,'Buy',100]
rows_list.append(list)
order_array=np.array(rows_list)
最佳答案
tldr:NumPy 在对数值数组进行数值计算时表现出色。虽然这是可能的(见下文),但 NumPy 并不适合这种情况。您可能最好使用 Pandas。
问题原因:
值被排序为字符串。您需要将它们排序为 int
。
In [7]: sorted(['15', '8'])
Out[7]: ['15', '8']
In [8]: sorted([15, 8])
Out[8]: [8, 15]
发生这种情况是因为 order_array
包含字符串。您需要在适当的地方将这些字符串转换为 int
。
将数据类型从字符串数据类型转换为数字数据类型需要为新数组分配空间。因此,您最好从一开始就修改创建 order_array
的方式。
有趣的是,即使您将值转换为整数,当您调用
order_array = np.array(rows_list)
NumPy 默认创建一个同类 数组。在同构数组中,每个值都具有相同的数据类型。所以 NumPy 试图找到你所有的共同点 值并选择了一个字符串数据类型,这阻碍了您将字符串转换为整数的努力!
您可以通过检查 order_array.dtype
自己检查数据类型:
In [42]: order_array = np.array(rows_list)
In [43]: order_array.dtype
Out[43]: dtype('|S4')
现在,我们如何解决这个问题?
使用对象数据类型:
最简单的方法是使用“对象”数据类型
In [53]: order_array = np.array(rows_list, dtype='object')
In [54]: order_array
Out[54]:
array([[2008, 1, 23, AAPL, Buy, 100],
[2008, 1, 30, AAPL, Sell, 100],
[2008, 1, 23, GOOG, Buy, 100],
[2008, 1, 30, GOOG, Sell, 100],
[2008, 9, 8, GOOG, Buy, 100],
[2008, 9, 15, GOOG, Sell, 100],
[2008, 5, 1, XOM, Buy, 100],
[2008, 5, 8, XOM, Sell, 100]], dtype=object)
这里的问题是 np.lexsort
或 np.sort
不适用于数组
dtype 对象
。要解决该问题,您可以对 rows_list
进行排序
在创建 order_list
之前:
In [59]: import operator
In [60]: rows_list.sort(key=operator.itemgetter(0,1,2))
Out[60]:
[(2008, 1, 23, 'AAPL', 'Buy', 100),
(2008, 1, 23, 'GOOG', 'Buy', 100),
(2008, 1, 30, 'AAPL', 'Sell', 100),
(2008, 1, 30, 'GOOG', 'Sell', 100),
(2008, 5, 1, 'XOM', 'Buy', 100),
(2008, 5, 8, 'XOM', 'Sell', 100),
(2008, 9, 8, 'GOOG', 'Buy', 100),
(2008, 9, 15, 'GOOG', 'Sell', 100)]
order_array = np.array(rows_list, dtype='object')
更好的选择是将前三列合并到 datetime.date 对象中:
import operator
import datetime as DT
for i in ...:
seq = [DT.date(int(x.year), int(x.month), int(x.day)) ,s_sym, 'Buy', 100]
rows_list.append(seq)
rows_list.sort(key=operator.itemgetter(0,1,2))
order_array = np.array(rows_list, dtype='object')
In [72]: order_array
Out[72]:
array([[2008-01-23, AAPL, Buy, 100],
[2008-01-30, AAPL, Sell, 100],
[2008-01-23, GOOG, Buy, 100],
[2008-01-30, GOOG, Sell, 100],
[2008-09-08, GOOG, Buy, 100],
[2008-09-15, GOOG, Sell, 100],
[2008-05-01, XOM, Buy, 100],
[2008-05-08, XOM, Sell, 100]], dtype=object)
尽管这很简单,但我不喜欢 dtype 对象的 NumPy 数组。 你既没有获得 NumPy 数组的速度也没有节省内存空间的 yield 原生数据类型。此时您可能会发现使用 Python 列表列表 更快,语法上更容易处理。
使用结构化数组:
一个更像 NumPy 的解决方案仍然提供速度和内存优势是
使用 structured array (与同构数组相反)。做一个
使用 np.array
的结构化数组,您需要显式提供 dtype:
dt = [('year', '<i4'), ('month', '<i4'), ('day', '<i4'), ('symbol', '|S8'),
('action', '|S4'), ('value', '<i4')]
order_array = np.array(rows_list, dtype=dt)
In [47]: order_array.dtype
Out[47]: dtype([('year', '<i4'), ('month', '<i4'), ('day', '<i4'), ('symbol', '|S8'), ('action', '|S4'), ('value', '<i4')])
要对结构化数组进行排序,您可以使用 sort
方法:
order_array.sort(order=['year', 'month', 'day'])
要使用结构化数组,您需要了解同构数组和结构化数组之间的一些区别:
您原来的同构数组是二维的。相比之下,所有 结构化数组是一维的:
In [51]: order_array.shape
Out[51]: (8,)
如果您使用 int 索引结构化数组或遍历数组,您 返回行:
In [52]: order_array[3]
Out[52]: (2008, 1, 30, 'GOOG', 'Sell', 100)
对于同构数组,您可以使用 order_array[:, i]
访问列
现在,使用结构化数组,您可以按名称访问它们:例如order_array['year']
。
或者,使用 Pandas:
如果可以安装Pandas ,我认为您可能最喜欢使用 Pandas DataFrame:
In [73]: df = pd.DataFrame(rows_list, columns=['date', 'symbol', 'action', 'value'])
In [75]: df.sort(['date'])
Out[75]:
date symbol action value
0 2008-01-23 AAPL Buy 100
2 2008-01-23 GOOG Buy 100
1 2008-01-30 AAPL Sell 100
3 2008-01-30 GOOG Sell 100
6 2008-05-01 XOM Buy 100
7 2008-05-08 XOM Sell 100
4 2008-09-08 GOOG Buy 100
5 2008-09-15 GOOG Sell 100
Pandas 有一些有用的函数,可以按日期对齐时间序列,填补缺失 值、分组和聚合/转换行或列。
通常情况下,使用单个日期列比年、月、日的三个整数值列更有用。
如果您需要将年、月、日作为单独的列用于输出,比如 csv,那么您可以将日期列替换为年、月、日列,如下所示:
In [33]: df = df.join(df['date'].apply(lambda x: pd.Series([x.year, x.month, x.day], index=['year', 'month', 'day'])))
In [34]: del df['date']
In [35]: df
Out[35]:
symbol action value year month day
0 AAPL Buy 100 2008 1 23
1 GOOG Buy 100 2008 1 23
2 AAPL Sell 100 2008 1 30
3 GOOG Sell 100 2008 1 30
4 XOM Buy 100 2008 5 1
5 XOM Sell 100 2008 5 8
6 GOOG Buy 100 2008 9 8
7 GOOG Sell 100 2008 9 15
或者,如果您对“日期”列一开始没有用处,您当然可以单独保留 rows_list
并从头开始使用年、月、日列构建 DataFrame。排序仍然很容易:
df.sort(['year', 'month', 'day'])
关于python - 在Python中的多列上对numpy数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19156472/