【问题标题】:Iterate through ndarray in Python在 Python 中遍历 ndarray
【发布时间】:2018-08-14 20:44:15
【问题描述】:

我有一个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 月,依此类推。

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

【问题讨论】:

  • 我不认为该数组代表 60 年中的所有月份,因为700/12 != 60。另外,您要完成的工作有点不清楚
  • 这没有任何意义。一个 700x100x100 的数组如何代表 60 年的几个月?这些维度都不能被 12 整除。如果是 60 年,为什么重新排列的数组中会连续出现 12 个一月,而不是 60 个?
  • 一个 (720,100,100) 数组可以重新整形为 (60,12,100,100)。
  • 如果数组跨度超过 60 年,那么一月不应该有 60 个元素等等吗?
  • 我添加了一些修改。我需要将 1958 年 1 月、1959 年、1960 年 1 月的整个 array 移动到一个新数组,这可能会导致 (12, 100, 100)。这个操作会一直重复到 12 月。所以在 I 中,要么有一个新的my_array.shape() > (720,100,100) 要么,12 new_array.shape() > (60, 100, 100)

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


【解决方案1】:

所以,请注意,如果您想要所有一月,您可以使用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 对象作为视图在原始数据上。如果迭代速度更重要,我会采用上述方法,因为以这种形式创建一个新数组会增加引用的局部性。

【讨论】:

    【解决方案2】:

    假设您的数组 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])
    

    【讨论】:

      【解决方案3】:

      根据@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
      

      【讨论】:

        猜你喜欢
        • 2013-06-25
        • 1970-01-01
        • 2020-03-02
        • 2020-08-18
        • 2015-01-11
        • 2019-05-07
        • 2023-03-29
        • 2021-04-21
        • 2018-06-19
        相关资源
        最近更新 更多