Как преобразовать кортеж глубины 2 в двумерный массив Numpy?
Следующий код не генерирует то, что я хочу; Чтобы преобразовать каждый кортеж внутри кортежа в массив Numpy, я могу получить значения с несколькими индексами.
import numpy as np
a=np.asarray([[1,2,3],[2,3,4,5]])
print a
Вывод ошибки:
IndexError: too many indices
Однако то, что я хочу получить, это 1, потому что первые кортежи, первые кортежи, первые значения, это одно. Как я должен сделать такое преобразование, чтобы это произошло?
Обновление: интересно, когда я пытаюсь что-то вроде:
a=np.asarray([np.asarray([1,2,3]),np.asarray([2,3,4,5])])
b=np.asarray([np.asarray([1,2,3]),np.asarray([2,3,4,5])])
print np.multiply(a,b)
Это создает желаемый результат! который является поэлементным умножением.
[array([1, 4, 9]) array([ 4, 9, 16, 25])]
2 ответа
Вы не можете преобразовать свой пример напрямую в массив NumPy, потому что у вас есть разные длины. В результате вы получаете массив 1d NumPy, который содержит объекты списка Python. Я видел, что вы пытаетесь сделать, называя его неровным массивом, но не уверен, что это какой-то официальный термин.
Вы можете заполнить элементы нулями или использовать разреженную матрицу, или просто не конвертировать в NumPy. Зависит от вашей общей цели.
Чтобы начать, вот как вы можете установить маскированный массив из зубчатого массива и вычислить сумму по оси. Кто-то, кто использует этот модуль больше меня, может предложить что-то более эффективное или идиоматическое:
>>> a = np.array([[[1,2,3],[2,3,4,5], [2, 2]],[[3,4,5,6,7],[1],[2,3,10]]])
>>> D = max(len(x) for x in y for y in a)
>>> padded = [[x + [0] * (D-len(x)) for x in y] for y in a]
>>> mask = [[[0] * len(x) + [1] * (D-len(x)) for x in y] for y in a]
>>> result = np.ma.masked_array(padded, np.array(mask, dtype=np.bool))
>>> result
masked_array(data =
[[[1 2 3 -- --]
[2 3 4 5 --]
[2 2 -- -- --]]
[[3 4 5 6 7]
[1 -- -- -- --]
[2 3 10 -- --]]],
mask =
[[[False False False True True]
[False False False False True]
[False False True True True]]
[[False False False False False]
[False True True True True]
[False False False True True]]],
fill_value = 999999)
>>> np.sum(result, axis=-1)
masked_array(data =
[[6 14 4]
[25 1 15]],
mask =
[[False False False]
[False False False]],
fill_value = 999999)
>>>
Если я поменяю a
а также b
поэтому numpy создает 2d-массив вместо массива массивов:
In [5]: am=np.asarray([np.asarray([1,2,3,0]),np.asarray([2,3,4,5])])
#array([[1, 2, 3, 0],
# [2, 3, 4, 5]])
In [7]: bm=np.asarray([np.asarray([1,2,3,0]),np.asarray([2,3,4,5])])
и делать время:
In [10]: timeit np.multiply(a,b)
100000 loops, best of 3: 7.94 us per loop
In [11]: timeit np.multiply(am,bm)
100000 loops, best of 3: 1.89 us per loop
Чистое умножение ndarray существенно быстрее. В одном случае он может перейти непосредственно к выполнению элемента путем умножения элемента (при быстром C
уровень кода); в другом он выполняет итерацию общего назначения, работая с объектами, а не с простыми числами. Это делает что-то похожее на итерации в Python.
На самом деле, если я сделаю этот цикл явно, я получу что-то близкое к этому более длительному времени
al,bl=a.tolist(), b.tolist()
In [21]: timeit np.array([np.multiply(x,y) for x,y in zip(al,bl)])
100000 loops, best of 3: 8.99 us per loop
Теперь давайте посмотрим на вашу проблему "сумма по последнему измерению". Сначала обратите внимание, что sum
(или же add.reduce
) не был расширен для работы с этим типом массива.
In [37]: timeit am.sum(axis=1)
100000 loops, best of 3: 11.5 us per loop
In [38]: timeit [x.sum() for x in a]
10000 loops, best of 3: 21.5 us per loop
Преимущество в скорости ndarray sum
не так хорошо sum
можно ускорить, кодируя его как dot
продукт (с np.dot
или же einsum
):
In [42]: timeit np.einsum('ij->i',am)
100000 loops, best of 3: 4.79 us per loop
In [50]: ones=np.array([1,1,1,1])
In [51]: timeit np.dot(am,ones)
100000 loops, best of 3: 2.37 us per loop
In [55]: timeit [np.einsum('j->',x) for x in a]
100000 loops, best of 3: 12.3 us per loop
In [64]: c=np.asarray([np.asarray([1,1,1]),np.asarray([1,1,1,1])])
In [65]: timeit [np.dot(x,y) for x,y in zip(a,c)]
100000 loops, best of 3: 8.12 us per loop
Таким образом, хотя можно создавать рваные массивы (или массивы массивов), они не имеют существенного преимущества в скорости перед списками массивов. Быстро numpy
Операции с массивами, как правило, не работают с элементами, которые являются объектами Python общего назначения (dtype=object
).