首页 > 解决方案 > 在 Python 中遍历 ndarray

问题描述

我有一个ndarray尺寸(720,100,100)。这ndarray代表 60 年内的所有月份,这意味着可以将它们按每年 12 个月分组。720表示从 1958 年到 2017 年(包括 1958 年)的月份,而(100, 100)用数据表示行和列。因此,前十二个ndarray属于 1958 年,第二包十二个属于 1959 年等等。值得一提的是,这些行和列中的一些“单元格”是空的。因此,将ndarray其保存为masked array(不是所有数据都这样的问题)。

我遇到的问题是:我如何遍历这个ndarray并将所有 1 月、2 月、3 月等“打包”在一起?因此,新的ndarray将具有相同的形状(720,100,100),但前 12 个arrays属于 1 月,接下来的 12 个属于 2 月,依此类推,所有年份。

我没有添加代码,因为它完全是这个操作的失败。

标签: pythonpython-3.xnumpymultidimensional-array

解决方案


所以,请注意,如果你想要所有一月,你可以numpy.ndarray在第一维上使用切片:

jans = arr[::12]

和所有的二月:

febs = arr[1::12]

所以,如果你真的想要一个“按月分组”的数组,那么简单的事情就是(使用一个只有 10 年数据的数组只是为了让事情变得更简单一些):

>>> import numpy as np
>>> x = np.arange(120*100*100, dtype=np.int32).reshape(120, 100, 100)
>>> grouped  = np.concatenate([x[i::12] for i in range(12)]) # O(n) operation!

这样做的好处是它将是 O(N) 时间,实际上,它只会对原始数组进行一次(尽管有点间接)扫描,因为在numpy.ndarray对象中切片会产生视图。这也将相当节省空间,只需要两倍多一点的空间(视图的一些辅助空间)。注意:

>>> grouped[:12][0]
array([[   0,    1,    2, ...,   97,   98,   99],
       [ 100,  101,  102, ...,  197,  198,  199],
       [ 200,  201,  202, ...,  297,  298,  299],
       ...,
       [9700, 9701, 9702, ..., 9797, 9798, 9799],
       [9800, 9801, 9802, ..., 9897, 9898, 9899],
       [9900, 9901, 9902, ..., 9997, 9998, 9999]], dtype=int32)
>>> grouped[:12][1]
array([[120000, 120001, 120002, ..., 120097, 120098, 120099],
       [120100, 120101, 120102, ..., 120197, 120198, 120199],
       [120200, 120201, 120202, ..., 120297, 120298, 120299],
       ...,
       [129700, 129701, 129702, ..., 129797, 129798, 129799],
       [129800, 129801, 129802, ..., 129897, 129898, 129899],
       [129900, 129901, 129902, ..., 129997, 129998, 129999]], dtype=int32)
>>> grouped[:12][2]
array([[240000, 240001, 240002, ..., 240097, 240098, 240099],
       [240100, 240101, 240102, ..., 240197, 240198, 240199],
       [240200, 240201, 240202, ..., 240297, 240298, 240299],
       ...,
       [249700, 249701, 249702, ..., 249797, 249798, 249799],
       [249800, 249801, 249802, ..., 249897, 249898, 249899],
       [249900, 249901, 249902, ..., 249997, 249998, 249999]], dtype=int32)
>>> grouped[:12][-1]
array([[130000, 130001, 130002, ..., 130097, 130098, 130099],
       [130100, 130101, 130102, ..., 130197, 130198, 130199],
       [130200, 130201, 130202, ..., 130297, 130298, 130299],
       ...,
       [139700, 139701, 139702, ..., 139797, 139798, 139799],
       [139800, 139801, 139802, ..., 139897, 139898, 139899],
       [139900, 139901, 139902, ..., 139997, 139998, 139999]], dtype=int32)

可能有一个更聪明的方法numpy.reshape,但我会让numpy这里的冠军尝试解决这个问题。以上对我来说似乎是一个不错的解决方案。

您可能会考虑的另一种选择是从月份数到视图的映射:

month_mapping  = {i:x[i::12] for i in range(12)]} # O(1) operation

现在,这将非常有效,因为映射的创建将是恒定的时间,并且您只需要 dict 的辅助空间(几百个字节)和 12 个numpy.ndarray将作为原始数据视图的对象。如果迭代的速度更重要,我会采用上述方法,因为以这种形式创建一个新数组会增加引用的局部性。


推荐阅读