【问题标题】:Convert array indexing code from 1D to 3D without using loops in python在不使用 python 循环的情况下将数组索引代码从 1D 转换为 3D
【发布时间】:2022-12-09 03:44:20
【问题描述】:

我有一个要索引的 3D 矩阵。索引是在 GUI 中选择的,因此它们可能超出范围。如果索引超出范围,我想在矩阵中设置值。现在我有一个代码可以用这样的循环来完成它:

list=[]
for i in range(): 
    if X,Y,Z out of range:
        a=1000
        list.append(a)
    else:  
        a=array_3d[X,Y,Z]
        list.append(a)

显然,当列表变长时,这是一种缓慢的方法。我有一个代码可以根据需要为一维列表编制索引。

'''

import numpy as np

class Set_Value(list):
    def _get_item_with_default(self, index, default_value):
        return super(Set_Value, self).__getitem__(index) if index >= 0 and index < len(self) else default_value

    def __getitem__(self, index):
        if isinstance(index, int):
            return self._get_item_with_default(index, 1000)
        elif isinstance(index, list):
            return [self._get_item_with_default(elem, 1000) for elem in index]

A=np.array([100,200,300,400])
S=Set_Value(A)
X=[1,1,1,1,1,1,1,1,1,1]
Y=[1,1,1,-5,-5,-5,1,1,1,1]
print(S[X])
print(S[Y])

'''

OUTPUT: 
[200, 200, 200, 200, 200, 200, 200, 200, 200, 200]
[200, 200, 200, 1000, 1000, 1000, 200, 200, 200, 200]

我正在努力将其转换为 3D,即

'''

import numpy as np
import random

Class TestC():
    #stuff to solve problem

array3d=np.random.randint(0,1000,size=(50,50,50))
set_3d=TestC(array3d)

X=random.sample(range(-100, 100), 100)
Y=random.sample(range(-100, 100), 100)
Z=random.sample(range(-100, 100), 100)
print(set_3d[X,Y,Z])

'''

OUTPUT: 

[value pulled from array3d, value pulled from array3d, set value to 1000 if out of range, set value to 1000 if out of range, ...]

在这一点上,我什至不确定它是否会更快,但我只是好奇它是否可以完成,但我无法让它工作。

【问题讨论】:

  • np.takenp.put 有一个clip 模式,但它们只能在一个维度上工作,或者一次展平数组。 np.clip 是一个可以约束数组值的通用函数。像x=np.arange(10); np.where(x&gt;5, 5, x)这样的表达式也可以用来裁剪一个数组。

标签: python arrays numpy class indexing


【解决方案1】:

hinted by hpauljnp.clipnp.where在这里很有用;无需创建自定义类。

# Convert all the indices into NumPy arrays
x, y, z = np.array(X), np.array(Y), np.array(Z)

# Keep track of out-of-range indices
is_x_oor = (x < 0) | (x >= array3d.shape[0])
is_y_oor = (y < 0) | (y >= array3d.shape[1])
is_z_oor = (z < 0) | (z >= array3d.shape[2])

# Ensure the indices stay within range
x = x.clip(0, array3d.shape[0] - 1)
y = y.clip(0, array3d.shape[1] - 1)
z = z.clip(0, array3d.shape[2] - 1)

# Perform indexing but take the default value if any index is out of range
res = np.where(is_x_oor | is_y_oor | is_z_oor, 1000, array3d[x, y, z])

然后,您可以将结果转换为带有 res.tolist() 的列表。

【讨论】:

  • 太好了,这有效。需要注意的一件事是,当我将其放入我的大代码中时,我必须在索引中将 x、y、z 转换为 int,即 array3d[x.astype(int)...]。我不确定我问这个问题的例子是否需要这样做,但我认为值得一提
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 2019-05-03
  • 1970-01-01
  • 2019-01-07
相关资源
最近更新 更多