As funções numpy.array e numpy.asarray têm um comportamento bem definido quando aplicadas a listas de arrays: se os arrays listados têm as mesmas dimensões e tamanho, a lista é transformada em uma das dimensões da matriz resultante (vamos chamá-la de " modo 1 "). Caso contrário, uma matriz de matrizes é retornada ("modo 2").
No entanto, o comportamento de numpy.array e numpy.asarray no "modo 2" parece depender do número de itens nos arrays. O código a seguir não é muito elegante em relação à utilidade entorpecente, mas funciona:
>>> a = np.array([1, 2, 3])
>>> b = np.array([[1, 0], [0, 1]])
>>> np.asarray([a, b])
array([array([1, 2, 3]), array([[1, 0],
[0, 1]])], dtype=object)
Mas o seguinte não:
>>> a = np.array([1, 2])
>>> b = np.array([[1, 0], [0, 1]])
>>> np.asarray([a, b])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.4/dist-packages/numpy/core/numeric.py", line 474, in asarray
return array(a, dtype, copy=False, order=order)
ValueError: could not broadcast input array from shape (2,2) into shape (2)
Claramente, o problema é que, quando numpy.asarray vê que a primeira dimensão tem o mesmo comprimento em a
e b
, ele tenta ir para o "modo 1", o que é impossível aqui.
EDIT: Estou usando numpy 1.10.4 e python 3.4.3.
Concordo, esse tipo de lógica alternativa é lamentável. Discutimos não fazer dtype=object
arrays a menos que o dtype seja explicitamente fornecido. IMO np.array([a, b], dtype=object)
deve ser a única maneira de escrever qualquer um desses - e não deve ser necessário fazer nenhuma verificação na forma.
Fornecer dtype=object
não ajuda - você ainda obtém o mesmo erro.
No entanto, adicionar uma matriz vazia permite evitá-lo:
arr_of_arr = np.array([np.array([]), a, b])[1:]
Ainda existe em 1.14.4
@ppwwyyxx - na verdade, em parte porque não é uma mudança trivial, em parte porque não é algo com que se atrapalhe o tempo todo, então a urgência é relativamente baixa (e não há tantas pessoas tendo tempo para contribuir ...).
Mas o que pode ajudar aqui é deixar mais claro qual seria exatamente o comportamento desejado. @shoyer mencionou a solicitação também de longa data para exigir explicitamente dtype=object
se isso for de fato desejado, caso contrário, levantando TypeError
para qualquer coisa que não possa ser analisada como um array numérico ou string (# 5353). Estive pensando recentemente se seria útil ter um dtype='structured'
, o que reforçaria estritamente uma diferença entre listas como elementos indicativos de uma matriz e tuplas como elementos de um tipo estruturado.
Estou disposto a contribuir se alguém puder me enviar algumas dicas sobre o que fazer. Acabei de dar uma olhada no código relacionado em ctors.c, a lógica do construtor parece ser bastante complicada, pois precisa lidar com muitas formas diferentes de entrada.
Mesmo problema: # 8330
Acho que isso pode ser corrigido por # 11601. Edit: Não é.
Então, o que está acontecendo aqui é mais ou menos:
a = np.array([1, 2])
b = np.array([[1, 0], [0, 1]])
out = np.asarray([a, b])
# translates to
out = np.empty((2, 2)) #shape is correctly inferred
out[0,:] = a
out[1,:] = b # error comes from here
Comentários muito úteis
Fornecer
dtype=object
não ajuda - você ainda obtém o mesmo erro.No entanto, adicionar uma matriz vazia permite evitá-lo: