python - 替换 n 维张量中给定索引的值 np.argwhere()

标签 python numpy tensor

我对 numpy 有点陌生,所以这可能是一个愚蠢的问题,但这里是:

假设我有一个任意形状和大小的张量,例如 (100,5,5)(3,3,10,15,4)。我有一个随机生成的索引列表,用于我想要用 np.nan 替换的点。对于 (3,3,3) 测试用例,如下所示:

>> data = np.random.randn(3,3,3)
>> data
array([[[ 0.21368315, -1.42814113,  1.23021783],
        [ 0.25835315,  0.44775156, -1.20489094],
        [ 0.25928972,  0.39486046, -1.79189447]],

       [[ 2.24080908, -0.89617961, -0.29550817],
        [ 0.21756087,  1.33996913, -1.24418745],
        [-0.63617598,  0.56848439,  0.8175564 ]],

       [[ 0.61367002, -1.16104071, -0.53488283],
        [ 1.0363354 , -0.76888041,  1.24524786],
        [-0.84329375, -0.61744489,  1.50502058]]])

>> idxs = np.argwhere(np.isfinite(data))
>> dropidxs = idxs[np.random.choice(idxs.shape[0], 3, replace=False)]
>> dropidxs
array([[1, 1, 1],
       [2, 0, 2],
       [2, 1, 0]])

如何替换相应的值?以前,当我只处理 3D 情况时,我使用以下方法进行操作。

for idx in dropidxs:
    i,j,k = dropidxs[idx]
    missingCube[i,j,k] = np.nan

但是现在,我希望该函数能够处理任何大小的张量。 我试过了

for idx in dropidxs:
    missingCube[idx] = np.nan

missingCube[dropidxs] = np.nan

但两者(不出所料)最终都会沿 axis=0 删除相应的切片。我应该如何处理这个问题?有没有更简单的方法来实现我想要做的事情?

最佳答案

In [486]: data = np.random.randn(3,3,3)

有了这个创造,所有项都是有限的,所以 nonzero返回 (27,) 数组的元组:

In [487]: idx = np.nonzero(np.isfinite(data))
In [488]: len(idx)
Out[488]: 3
In [489]: idx[0].shape
Out[489]: (27,)

argwhere产生相同的数字,但在二维数组中:

In [490]: idxs = np.argwhere(np.isfinite(data))
In [491]: idxs.shape
Out[491]: (27, 3)

因此您选择了一个子集。

In [492]: dropidxs = idxs[np.random.choice(idxs.shape[0], 3, replace=False)]
In [493]: dropidxs.shape
Out[493]: (3, 3)
In [494]: dropidxs
Out[494]: 
array([[1, 1, 0],
       [2, 1, 2],
       [2, 1, 1]])

我们可以通过 x = np.random.choice(...) 生成相同的子集,并应用该xidxs 中的数组。但在这种情况下,argwhere 数组更容易使用。

但是要将该数组应用于索引,我们仍然需要一个数组元组:

In [495]: tup = tuple([dropidxs[:,i] for i in range(3)])
In [496]: tup
Out[496]: (array([1, 2, 2]), array([1, 1, 1]), array([0, 2, 1]))
In [497]: data[tup]
Out[497]: array([-0.27965058,  1.2981397 ,  0.4501406 ])
In [498]: data[tup]=np.nan
In [499]: data
Out[499]: 
array([[[-0.4899279 ,  0.83352547, -1.03798762],
        [-0.91445783,  0.05777183,  0.19494065],
        [ 0.6835925 , -0.47846423,  0.13513958]],

       [[-0.08790631,  0.30224828, -0.39864576],
        [        nan, -0.77424244,  1.4788093 ],
        [ 0.41915952, -0.09335664, -0.47359613]],

       [[-0.40281937,  1.64866377, -0.40354504],
        [ 0.74884493,         nan,         nan],
        [ 0.13097487, -1.63995208, -0.98857852]]])

或者我们可以使用以下索引:

In [500]: data[dropidxs[:,0],dropidxs[:,1],dropidxs[:,2]]
Out[500]: array([nan, nan, nan])

实际上,是 dropidxs 的转置可能会更方便:

In [501]: tdrop = dropidxs.T
In [502]: tuple(tdrop)
Out[502]: (array([1, 2, 2]), array([1, 1, 1]), array([0, 2, 1]))
In [503]: data[tuple(tdrop)]
Out[503]: array([nan, nan, nan])

有时我们可以使用*将列表/数组扩展为元组,但在索引时不扩展:

In [504]: data[*tdrop]
  File "<ipython-input-504-cb619d907adb>", line 1
    data[*tdrop]
         ^
SyntaxError: invalid syntax

但是我们可以使用以下方法创建元组:

In [506]: data[(*tdrop,)]
Out[506]: array([nan, nan, nan])

关于python - 替换 n 维张量中给定索引的值 np.argwhere(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71164908/

相关文章:

python - 使用表示索引的一维长张量选择 3D Pytorch 张量的特定索引

C++ 通过编译时移位来访问基于 1 而不是 0 的数组

python - Django - 如何在保存之前获取字段值?

java - 为什么按位左移在 Python 和 Java 中返回不同的结果?

python - 如何在 python numpy 中从周围的白色背景中裁剪对象?

python - Scipy 稀疏 dia_matrix 求解器

python - AWS Sagemaker 推理端点未利用所有 vCPU

python - SqlAlchemy:如何在 where 子句中使用选定子查询的结果

python - InterX 到 python 的翻译代码出现故障

python - 向量外积的泛化 : apply it to every column of a matrix