【问题标题】:A 2d matrix can be reconstructed, in which a mask has been used with numpy where and flattened可以重建 2d 矩阵,其中掩码已与 numpy where 和 flattened 一起使用
【发布时间】:2021-02-10 12:38:14
【问题描述】:

正如问题所说,我有一个二维矩阵 (1000, 2000),我在其中应用 numpy where 函数的条件,以这种方式:

import numpy as np

A = np.random.randn(1000, 2000)
print(A.shape)
(1000, 2000)
mask = np.where((A >=0.1) & (A <= 0.5))

A = A[mask]
print(A.shape)
(303112,)

我得到一个展平矩阵,我将其用作仅支持一维矩阵的 Fortran 程序中的输入,该程序的输出与输入一维矩阵具有相同的维度 (303112,),是否有任何方法或功能可以将展平矩阵重建为其原始 2D 形式。我正在考虑将索引保存在布尔矩阵中并使用它们来重建矩阵,如果有人知道任何 numpy 方法或任何建议会有很大帮助。

您好。

【问题讨论】:

  • 为了得到一个布尔矩阵,你可以试试:np.logical_and(A &gt;= 0.1, A &lt;= 0.5),如果我需要更明确的告诉我
  • 您需要维护掩码中存在的索引的 1D 和 2D 版本。本质上,您想将 2D 蒙版转换为 1D,进行处理。然后从 1D 掩码中获取 2D 索引。您可以使用np.ravel_multi_index 获取一维索引,并使用这些一维索引使用np.unravel_index 获取原始二维索引,详情请查看我的答案。
  • res[mask]= new_values 是否工作,其中res 具有所需的二维形状。

标签: python python-3.x numpy


【解决方案1】:

IIUC 您需要维护掩码的 1D 索引和 2D 索引,以便当您尝试使用 FORTRAN 程序更新这些值时,您可以切换到 1D 进行输入,然后切换回 2D 以更新原始数组。

您可以使用np.ravel_multi_index 将二维索引转换为一维。然后,您可以使用这些 1D 索引使用np.unravel_index 将它们转换回 2D(尽管由于您已经拥有 2D 蒙版,因此无需再次将 1D 转换为 2D。)

import numpy as np

A = np.random.randn(1000, 2000)
mask = np.where((A >=0.1) & (A <= 0.5))

idx_flat = np.ravel_multi_index(mask, (1000,2000)) #FLAT 1D indexes using original mask
idx_2d = np.unravel_index(idx_flat, (1000,2000))   #2D INDEXES using the FLAT 1D indexes


#Comparing the method of using flat indexes and A[mask]
print(np.allclose(A.ravel()[idx_flat],A[mask])) 
### True

#Comparing the freshly created 2d indexes to the original mask
print(np.allclose(idx_2d,mask))
### True

这是一个带有 (3,3) 矩阵的端到端代码的虚拟测试用例。

import numpy as np

#Dummy matrix A and mask
A = np.random.randn(3, 3)  #<---- shape (3,3)
mask = np.where(A <= 0.5)
mask[0].shape  #Number of indexes in 2D mask
###Output: (6,)

#########################################################

#Flatten 2D indexes to 1D
idx_flat = np.ravel_multi_index(mask, (3,3)) #<--- shape (3,3)
idx_flat.shape  #Number of indexes in flattened mask
###Output: (6,)

#########################################################

#Feed the 6 length array to fortran function
def fortran_function(x):
    return x**2

flat_array = A.ravel()[idx_flat]
fortran_output = fortran_function(flat_array)

#Number of values in fortran_output
fortran_output.shape
###Output: (6,)

#########################################################

#Create a empty array 
new_arr = np.empty((3,3))  #<---- shape (3,3)
new_arr[:] = np.nan
new_arr[mask] = fortran_output   #Feed the 1D array to the 2D masked empty array

new_arr
array([[5.63399114e-04,            nan, 7.86255167e-01],
       [3.94992857e+00, 4.88932044e-02, 2.45489069e+00],
       [3.51957270e-02,            nan,            nan]])

【讨论】:

  • 感谢您的回答,但是根据示例 303112 值,FORTRAN 程序中的输入矩阵只能是值范围(>=0.1 和
  • 这里的一维矩阵不是1000X2000,还是303112
  • 你只是单独维护303112个索引
  • 我已经更新了我的代码,以便通过 (3,3) 矩阵的分步示例提供更多信息。
  • 完美,感谢这个例子,它帮助我澄清了问题,我通过压缩使用列表获得了很好的结果,替换了布尔数组为 TRUE 但效率较低的方法,非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2013-07-31
  • 2014-03-24
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 1970-01-01
  • 2019-01-29
  • 1970-01-01
相关资源
最近更新 更多