Если вы создаете массив dtype объекта, вы можете поместить в слоты все что угодно:
In [9]: a = np.empty((2,2), object)
In [10]: a
Out[10]:
array([[None, None], # empty() fills with None
[None, None]], dtype=object)
In [11]: for i in range(2):
...: for j in range(2):
...: a[i,j] = {'x':b[i], 'y':c[j]}
...:
In [12]: a
Out[12]:
array([[{'x': 1, 'y': 4}, {'x': 1, 'y': 3}],
[{'x': 3, 'y': 4}, {'x': 3, 'y': 3}]], dtype=object)
Но понимание списка работает так же хорошо
In [13]: [[{'x':b[i],'y':c[j]} for j in range(2)] for i in range(2)]
Out[13]: [[{'x': 1, 'y': 4}, {'x': 1, 'y': 3}], [{'x': 3, 'y': 4}, {'x': 3, 'y': 3}]]
In [14]: np.array(_)
Out[14]:
array([[{'x': 1, 'y': 4}, {'x': 1, 'y': 3}],
[{'x': 3, 'y': 4}, {'x': 3, 'y': 3}]], dtype=object)
Или вы можете начать сплоский список и измените массив:
In [15]: [{'x':b[i],'y':c[j]} for j in range(2) for i in range(2)]
Out[15]: [{'x': 1, 'y': 4}, {'x': 3, 'y': 4}, {'x': 1, 'y': 3}, {'x': 3, 'y': 3}]
In [16]: np.array(_)
Out[16]:
array([{'x': 1, 'y': 4}, {'x': 3, 'y': 4}, {'x': 1, 'y': 3},
{'x': 3, 'y': 3}], dtype=object)
In [18]: _.reshape(2,2)
Out[18]:
array([[{'x': 1, 'y': 4}, {'x': 3, 'y': 4}],
[{'x': 1, 'y': 3}, {'x': 3, 'y': 3}]], dtype=object)
Этот массив словарей не будет проще и быстрее использовать, чем список (ы).
В качестве альтернативы мы могли бы создатьструктурированный массив с 2 именованными полями.Начнем со списка кортежей:
In [19]: [(b[i],c[j]) for j in range(2) for i in range(2)]
Out[19]: [(1, 4), (3, 4), (1, 3), (3, 3)]
In [20]: np.array(_, dtype=[('x',int),('y',int)])
Out[20]: array([(1, 4), (3, 4), (1, 3), (3, 3)], dtype=[('x', '<i8'), ('y', '<i8')])
In [21]: _.reshape(2,2)
Out[21]:
array([[(1, 4), (3, 4)],
[(1, 3), (3, 3)]], dtype=[('x', '<i8'), ('y', '<i8')])
In [22]: _['x']
Out[22]:
array([[1, 3],
[1, 3]])
В отличие от этого, чтобы получить все значения x
из массива объектов 2d:
In [24]: [i['x'] for i in a.flat]
Out[24]: [1, 1, 3, 3]