您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

在Python中的多列上排序numpy数组

在Python中的多列上排序numpy数组

tldr:在对数值数组进行数值计算时,NumPy会发光。尽管有可能(参见下文),但NumPy不太适合此操作。您最好使用Pandas。

这些值 将按字符串 排序。您需要将它们排序为ints

In [7]: sorted(['15', '8'])
Out[7]: ['15', '8']

In [8]: sorted([15, 8])
Out[8]: [8, 15]

发生这种情况是因为order_array包含字符串。您需要将这些字符串转换ints适当的位置。

将dtype从string-dtype转换为数字dtype需要为新数组分配空间。因此,order_array从一开始就修改创建方式可能会更好。

有趣的是,即使您将值转换为整数,当您调用

order_array = np.array(rows_list)

认情况下,NumPy创建一个 同质 数组。在齐次数组中,每个值都具有相同的dtype。因此,NumPy尝试在所有值中找到公分母,并选择了字符串dtype,从而阻碍了您将字符串转换为int的工作!

您可以通过检查order_array.dtype以下内容来自己检查dtype :

In [42]: order_array = np.array(rows_list)

In [43]: order_array.dtype
Out[43]: dtype('|S4')

现在,我们如何解决这个问题?

最简单的方法是使用’object’dtype

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不要在D型的阵列工作object。为了解决这个问题,您可以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数组。使用本地dtypes不会获得NumPy阵列的速度或节省内存空间的收益。在这一点上,您可能会发现使用python列表列表更快,语法上更容易处理。

仍然具有速度和内存优势的NumPy- ish解决方案是使用结构化数组(而不是同类数组)。要使用结构化数组,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] Now来访问列,对于结构化数组,可以按名称访问它们:例如order_array['year']

如果您可以安装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

熊猫具有有用的功能,可以按日期对齐时间序列,填充缺失值,分组和汇总/转换行或列。

通常,使用一个日期列而不是用于年,月,日的三个整数值的列更为有用。

如果您需要年,月,日作为单独的列以便输出,例如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

或者,如果您没有用“ date”列作为开始,那么您当然可以rows_list不理会,并从开始就用年,月,日列来构建DataFrame。排序仍然很容易:

df.sort(['year', 'month', 'day'])
python 2022/1/1 18:33:12 有195人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶