Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Numpy:基于dict中的值创建二维数组,使用其他二维数组值作为索引_Python_Arrays_Numpy_Dictionary - Fatal编程技术网

Python Numpy:基于dict中的值创建二维数组,使用其他二维数组值作为索引

Python Numpy:基于dict中的值创建二维数组,使用其他二维数组值作为索引,python,arrays,numpy,dictionary,Python,Arrays,Numpy,Dictionary,我有2个2D numpy阵列: a = np.array([['a', 'b', 'c'], ['d', 'e', 'f']]) b = np.array([[0.01, 0.02, 0.03], [0.04, 0.05, 0.06]]) 我有一个带有一些值的dict: d = {'a': 100, 'b': 200, ... 'f':600} 现在,我想基于前2个和我的dict创建一个2D数组。类似于: c = b * d[a] 换句话说,我想使用与数组a中相同索引处的值相对应的特定值(

我有2个2D numpy阵列:

a = np.array([['a', 'b', 'c'], ['d', 'e', 'f']])
b = np.array([[0.01, 0.02, 0.03], [0.04, 0.05, 0.06]])
我有一个带有一些值的dict:

d = {'a': 100, 'b': 200, ... 'f':600}
现在,我想基于前2个和我的dict创建一个2D数组。类似于:

c = b * d[a]
换句话说,我想使用与数组
a
中相同索引处的值相对应的特定值(从dict
d
检索)来操作数组
b

c = np.array([[1, 4, 9], [16, 25, 36]])
除了嵌套循环之外,还有什么方法可以做到这一点吗?

您可以使用
d.get
方法上的函数将
a
的值用作
d
的键:

>>> np.vectorize(d.get)(a)
array([[100, 200, 300],
       [400, 500, 600]])
请注意,这是作为后台循环实现的,因此不会给您带来太多(如果有的话)性能好处

您可以将其合并为一行:

>>> b*np.vectorize(d.get)(a)
array([[  1.,   4.,   9.],
       [ 16.,  25.,  36.]])
您可以使用
d.get
方法上的函数使用
a
的值作为
d
的键:

>>> np.vectorize(d.get)(a)
array([[100, 200, 300],
       [400, 500, 600]])
请注意,这是作为后台循环实现的,因此不会给您带来太多(如果有的话)性能好处

您可以将其合并为一行:

>>> b*np.vectorize(d.get)(a)
array([[  1.,   4.,   9.],
       [ 16.,  25.,  36.]])

这里有一个矢量化的方法,在这个过程中使用NumPy函数-

# Convert strings in a to numeric labels
aID = (np.fromstring(a, dtype=np.uint8)-97).reshape(a.shape)

# Get the argsort for getting sorted keys from dictionary
dk = d.keys()
sidx = np.searchsorted(sorted(dk),dk)

# Extract values from d and sorted by the argsort indices.
# Then, index with the numeric labels from a and multiply with b.
d_vals= np.take(d.values(),sidx)
out = b*d_vals[aID]
请注意,这些键被假定为单字符串。如果它们不是那种格式,您可以使用
np.unique
获取与
a
中的元素对应的数字标签,如下所示-

aID = np.unique(a,return_inverse=True)[1].reshape(a.shape)
运行时测试

在本节中,让我们使用那些
6键
和更大的数组,并对迄今为止发布的所有方法进行计时,包括问题中建议的原始方法-

In [238]: def original_app(a,b,d): # From question
     ...:     c = np.zeros(a.shape)
     ...:     for i in range(a.shape[0]):
     ...:         for j in range(a.shape[1]):
     ...:             c[i,j] = b[i,j] * d[a[i,j]]
     ...:     return c
     ...: 
     ...: def vectorized_app(a,b,d): # Proposed code earlier
     ...:     aID = (np.fromstring(a, dtype=np.uint8)-97).reshape(a.shape)
     ...:     dk = d.keys()
     ...:     sidx = np.searchsorted(sorted(dk),dk)
     ...:     d_vals= np.take(d.values(),sidx)
     ...:     return b*d_vals[aID]
     ...: 

In [239]: # Setup inputs
     ...: M, N = 400,500 # Dataisze
     ...: d = {'a': 600, 'b': 100, 'c': 700, 'd': 550, 'e': 200, 'f':80}
     ...: strings = np.array(d.keys())
     ...: a = strings[np.random.randint(0,6,(M,N))]
     ...: b = np.random.rand(*a.shape)
     ...: 

In [240]: %timeit original_app(a,b,d)
1 loops, best of 3: 219 ms per loop

In [241]: %timeit b*np.vectorize(d.get)(a) # @TheBlackCat's solution
10 loops, best of 3: 34.9 ms per loop

In [242]: %timeit vectorized_app(a,b,d)
100 loops, best of 3: 3.17 ms per loop

In [243]: np.allclose(original_app(a,b,d),vectorized_app(a,b,d))
Out[243]: True

In [244]: np.allclose(original_app(a,b,d),b*np.vectorize(d.get)(a))
Out[244]: True

这里有一个矢量化的方法,在这个过程中使用NumPy函数-

# Convert strings in a to numeric labels
aID = (np.fromstring(a, dtype=np.uint8)-97).reshape(a.shape)

# Get the argsort for getting sorted keys from dictionary
dk = d.keys()
sidx = np.searchsorted(sorted(dk),dk)

# Extract values from d and sorted by the argsort indices.
# Then, index with the numeric labels from a and multiply with b.
d_vals= np.take(d.values(),sidx)
out = b*d_vals[aID]
请注意,这些键被假定为单字符串。如果它们不是那种格式,您可以使用
np.unique
获取与
a
中的元素对应的数字标签,如下所示-

aID = np.unique(a,return_inverse=True)[1].reshape(a.shape)
运行时测试

在本节中,让我们使用那些
6键
和更大的数组,并对迄今为止发布的所有方法进行计时,包括问题中建议的原始方法-

In [238]: def original_app(a,b,d): # From question
     ...:     c = np.zeros(a.shape)
     ...:     for i in range(a.shape[0]):
     ...:         for j in range(a.shape[1]):
     ...:             c[i,j] = b[i,j] * d[a[i,j]]
     ...:     return c
     ...: 
     ...: def vectorized_app(a,b,d): # Proposed code earlier
     ...:     aID = (np.fromstring(a, dtype=np.uint8)-97).reshape(a.shape)
     ...:     dk = d.keys()
     ...:     sidx = np.searchsorted(sorted(dk),dk)
     ...:     d_vals= np.take(d.values(),sidx)
     ...:     return b*d_vals[aID]
     ...: 

In [239]: # Setup inputs
     ...: M, N = 400,500 # Dataisze
     ...: d = {'a': 600, 'b': 100, 'c': 700, 'd': 550, 'e': 200, 'f':80}
     ...: strings = np.array(d.keys())
     ...: a = strings[np.random.randint(0,6,(M,N))]
     ...: b = np.random.rand(*a.shape)
     ...: 

In [240]: %timeit original_app(a,b,d)
1 loops, best of 3: 219 ms per loop

In [241]: %timeit b*np.vectorize(d.get)(a) # @TheBlackCat's solution
10 loops, best of 3: 34.9 ms per loop

In [242]: %timeit vectorized_app(a,b,d)
100 loops, best of 3: 3.17 ms per loop

In [243]: np.allclose(original_app(a,b,d),vectorized_app(a,b,d))
Out[243]: True

In [244]: np.allclose(original_app(a,b,d),b*np.vectorize(d.get)(a))
Out[244]: True

虽然这是矢量化的,但一旦获得唯一值并进行排序和搜索,就失去了矢量化的速度优势。@Blackcat设置矢量化肯定会有一些开销。我想这取决于输入数据的格式。使用
d
我希望它的密钥数量有限,这样排序就不会太昂贵。让我们来看看它是如何与OP.the blackcat合作的。好吧,摆脱了
np.unique
!现在一定快多了,非常感谢您的反馈!虽然这是矢量化的,但一旦获得唯一值并进行排序和搜索,就失去了矢量化的速度优势。@Blackcat设置矢量化肯定会有一些开销。我想这取决于输入数据的格式。使用
d
我希望它的密钥数量有限,这样排序就不会太昂贵。让我们来看看它是如何与OP.the blackcat合作的。好吧,摆脱了
np.unique
!现在一定快多了,非常感谢您的反馈!您可以通过某种循环(隐藏或显式)中的键访问字典元素,或者使用
键/值/项
提取所有值并创建更适合数组使用的其他结构。您可以通过某种循环(隐藏或显式)中的键访问字典元素,或者使用
键/值/项
提取所有值并创建更适合数组使用的其他结构。