[英]How to initialize locations of numpy array using dictionary keys and values?
I have the following numpy array which is basically a 3 channel image:我有以下 numpy 数组,它基本上是一个 3 通道图像:
arr = np.zeros((6, 4, 3), dtype=np.float32)
# dictionary of values, key is array location
values_of_channel_0 = {
(0, 2) : 1,
(1, 0) : 1,
(1, 3) : 5,
(2, 1) : 2,
(2, 2) : 3,
(2, 3) : 1,
(3, 0) : 1,
(3, 2) : 2,
(4, 0) : 2,
(4, 2) : 20,
(5, 0) : 1,
(5, 2) : 10,
(5, 3) : 1
}
I am trying to find the most elegant way to set all the values of the 3rd channel according to the dictionary.我正在尝试根据字典找到最优雅的方式来设置第三通道的所有值。 Here is what I tried:这是我尝试过的:
locations = list(values_of_channel_0.keys())
values = list(values_of_channel_0.values())
arr[lc,0] = values # trying to set the 3rd channel
But this fails.但这失败了。
Is there a way in which this can be done without looping over keys and values?有没有一种方法可以在不循环键和值的情况下完成?
What's wrong with a simple loop?一个简单的循环有什么问题? Something will have to iterate over the key/value-pairs you provide in your dictionary in any case?在任何情况下都必须迭代您在字典中提供的键/值对?
import numpy as np
arr = np.zeros((6, 4, 3), dtype=np.float32)
# dictionary of values, key is array location
values_of_channel_0 = {
(0, 2) : 1,
(1, 0) : 1,
(1, 3) : 5,
(2, 1) : 2,
(2, 2) : 3,
(2, 3) : 1,
(3, 0) : 1,
(3, 2) : 2,
(4, 0) : 2,
(4, 2) : 20,
(5, 0) : 1,
(5, 2) : 10,
(5, 3) : 1
}
for (a, b), v in values_of_channel_0.items():
arr[a, b, 0] = v
print(arr)
Result:结果:
[[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 1. 0. 0.]
[ 0. 0. 0.]]
[[ 1. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]
[ 5. 0. 0.]]
[[ 0. 0. 0.]
[ 2. 0. 0.]
[ 3. 0. 0.]
[ 1. 0. 0.]]
[[ 1. 0. 0.]
[ 0. 0. 0.]
[ 2. 0. 0.]
[ 0. 0. 0.]]
[[ 2. 0. 0.]
[ 0. 0. 0.]
[20. 0. 0.]
[ 0. 0. 0.]]
[[ 1. 0. 0.]
[ 0. 0. 0.]
[10. 0. 0.]
[ 1. 0. 0.]]]
If you insist on not looping for the assignment, you can construct a data structure that can be assigned at once:如果坚持不循环赋值,可以构造一个可以一次性赋值的数据结构:
channel_0 = [[values_of_channel_0[b, a] if (b, a) in values_of_channel_0 else 0 for a in range(4)] for b in range(6)]
arr[..., 0] = channel_0
But this is clearly rather pointless and not even more efficient.但这显然毫无意义,甚至效率更高。 If you have some control over how values_of_channel_0
is constructed, you could consider constructing it as a nested list or array of the right dimensions immediately, to allow for this type of assignment.如果您对values_of_channel_0
的构建方式有一定的控制权,您可以考虑立即将其构建为正确维度的嵌套列表或数组,以允许此类分配。
Users @mechanicpig and @michaelszczesny offer a very clean alternative (which will be more efficient since it relies on the efficient implementation of zip()
):用户@mechanicpig 和@michaelszczesny 提供了一个非常干净的替代方案(由于它依赖于zip()
的高效实现,因此效率更高):
arr[(*zip(*values_of_channel_0), 0)] = list(values_of_channel_0.values())
Edit: you asked for an explanation of the lefthand side.编辑:您要求对左侧进行解释。
This hinges on the unpacking operator *
.这取决于拆包运算符*
。 *values_of_channel_0
spreads all the keys of the dictionary values_of_channel_0
into a call to zip()
. *values_of_channel_0
将字典values_of_channel_0
的所有键传播到对zip()
的调用中。 Since these keys are all 2- tuple
s of int
, zip will yield two tuples, one with all the first coordinates (0, 1, 1, ...)
and the second with the second coordinates (2, 0, 3, ...)
.由于这些键都是int
的双tuple
组,因此 zip 将产生两个元组,一个具有所有第一个坐标(0, 1, 1, ...)
,第二个具有第二个坐标(2, 0, 3, ...)
。
Since the call to zip()
is also preceded by *
, these two values will be spread to index arr[]
, together with a final coordinate 0
.由于对zip()
的调用也以*
开头,这两个值将与最终坐标0
一起扩展到索引arr[]
。 So this:所以这:
arr[(*zip(*values_of_channel_0), 0)] = ...
Is essentially the same as:本质上是一样的:
arr[((0, 1, 1, ...), (2, 0, 3, ...), 0)] = ...
That's a slice of arr
with exactly the same number of elements as the dictionary, including all the elements with the needed coordinates.这是arr
的一部分,其元素数量与字典完全相同,包括具有所需坐标的所有元素。 And so assigning list(values_of_channel_0.values())
to it works and has the desired effect of assigning the matching values to the correct coordinates.因此,将list(values_of_channel_0.values())
分配给它会起作用,并且具有将匹配值分配给正确坐标的预期效果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.