#python #numpy #stack
Вопрос:
Я пытаюсь сложить массивы numpy, которые хранятся в словаре. До сих пор я нашел несколько способов сделать это. К сожалению, самый элегантный код печатает предупреждение о будущем:
sys:1: FutureWarning: arrays to stack must be passed as a "sequence" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.
.
ПРИМЕР КОДА № 1 (не содержит предупреждения, но слишком громоздок):
data_stack = np.stack([data_matrix[0], data_matrix[1], data_matrix[2], data_matrix[3], data_matrix[4], data_matrix[5], data_matrix[6], data_matrix[7], data_matrix[8], data_matrix[9], data_matrix[10], data_matrix[11]], axis=1)
.
ПРИМЕР КОДА № 2 (более краткий и по-прежнему не содержит предупреждения):
data_stack = np.stack([data_matrix[key] for key in data_matrix.keys()], axis=1)
.
ПРИМЕР КОДА № 3 (этот мне нравится больше всего, но он предупреждает):
data_stack = np.stack(data_matrix.values(), axis=1)
Я попытался исправить это следующим образом:
data_stack = np.stack([data_matrix.values()], axis=1)
Но это, похоже, полностью нарушает код:
Traceback (most recent call last):
File "./CLN40ULPEF_PttV1350W1350G0000S0000T025.lib.py", line 261, in <module>
data_stack = np.stack([data_matrix.values()], axis=1)
File "<__array_function__ internals>", line 5, in stack
File "/usr/lib64/python3.9/site-packages/numpy/core/shape_base.py", line 430, in stack
axis = normalize_axis_index(axis, result_ndim)
numpy.AxisError: axis 1 is out of bounds for array of dimension 1
.
Есть ли (простой) способ заставить data_matrix.values()
работать numpy.stack
без предупреждения?
Комментарии:
1. Вы , вероятно, могли бы это сделать
list(data_matrix.values())
, но, конечно, любая операция увеличивает вычислительное время.2. @mapf, добавление
list
сюда не повредит времени.stack
повторяет все элементы входного аргумента, добавляя измерение.3. @hpaulj приятно знать, спасибо!
4. Расширение a
dict.values()
до полного списка-это нормально.
Ответ №1:
Первое, что np.stack
происходит после использования функции предупреждения генератора ( arrays = _arrays_for_stack_dispatcher(arrays, stacklevel=6)
),-это:
arrays = [asanyarray(arr) for arr in arrays]
затем он проверяет соответствие фигур
shapes = {arr.shape for arr in arrays}
и расширяет размеры массива
expanded_arrays = [arr[sl] for arr in arrays]
Это множество вариантов понимания списка.
Попытка сэкономить ввод текста или время, передавая dict_values
генератор вместо списка, является пустой тратой вашего времени и усилий.
In [159]: adict.values()
Out[159]:
dict_values([array([[1., 1.],
[1., 1.],
[1., 1.]]), array([[0., 0.],
[0., 0.],
[0., 0.]])])
In [160]: list(adict.values())
Out[160]:
[array([[1., 1.],
[1., 1.],
[1., 1.]]),
array([[0., 0.],
[0., 0.],
[0., 0.]])]
Применение списка к values()
обычной практике Python3. Например, вы не можете индексировать генератор:
In [162]: adict.values()[0]
Traceback (most recent call last):
File "<ipython-input-162-23f4ccd9e2f7>", line 1, in <module>
adict.values()[0]
TypeError: 'dict_values' object is not subscriptable
In [163]: list(adict.values())[0]
Out[163]:
array([[1., 1.],
[1., 1.],
[1., 1.]])
Ответ №2:
Здесь
data_stack = np.stack([data_matrix[key] for key in data_matrix.keys()], axis=1)
вы перебираете ключи data_matrix
dict
и извлекаете значение для каждого заданного ключа. Вместо этого вы можете просто перебирать значения, т. Е.:
data_stack = np.stack([v for v in data_matrix.values()], axis=1)
Комментарии:
1. В комментарии было предложено
list(dict.values())
, что в принципе одно и то же.
Ответ №3:
Спасибо всем вам за вашу помощь. Подходящий ответ можно найти в одном из комментариев @mapf. Поэтому я собираюсь опубликовать его здесь в качестве окончательного решения:
data_stack = np.stack(list(data_matrix.values()), axis=1)