Способы избежать предупреждения о будущем numpy.stack?

#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)