在Python中遍历ndarray

时间:2018-08-14 20:44:16

标签: python python-3.x numpy multidimensional-array

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

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

我没有添加代码,因为它是此操作的完整重击。

3 个答案:

答案 0 :(得分:1)

因此,请注意,如果要使用所有Januaries,则可以在第一维上使用numpy.ndarray切片:

jans = arr[::12]

以及所有2月:

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对象进行切片会产生 views 。这也将是相当节省空间的,只需要两倍于两倍的空间(用于视图的一些辅助空间)即可。注意:

>>> 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

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

答案 1 :(得分:0)

假设您的数组a将月份存储为0到11之间的整数,则类似的操作将按月将行分组为单独的数组:

month_arrays = {i:None for i in range(0,12)} #initialize a dictionary for mapping months to arrays
a = ... #your array
for row in a:
    month_index = row[0][0] #get the first element of the row
    if month_arrays[month_index] == None:
        month_arrays[month_index] = row
    else:
        np.vstack([month_arrays[month_index], row])

答案 2 :(得分:0)

在@ juanpa.arrivillaga已经发布的内容之后,您可以使用以下函数遍历数组。

import numpy as np

def dataMonth (_data, _months):
    """ This function returns the original data agrouped by months through the years."""

    _ind_months = []

    _number_months = list(range(_months))

    _grouped_months  = np.concatenate([_data[i::12] for i in range(12)]) #Credits to juanpa.arrivillaga

    for i in _number_months:
        #print (i)
        _temp = _data[i::12]
        _ind_months.append(_temp)

    return _grouped_months, _ind_months