Странное поведение numpy vstack / c_ при составлении списка идентичных массивов - PullRequest
1 голос
/ 13 февраля 2020

Я пытаюсь сложить три отдельных списка смешанного типа в матрицу.

Например, что-то вроде этого работает отлично:

import numpy as np


In [31]:

c1 = [0, [1], [1], [1], [1], [1], [1], [1], [1], [1]]
c2 = [[1], 0, 0, [1], [1], [1], [1], [1], 0, [1]]
c3 = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

In [32]:

np.c_[c1,c2,c3]

Out[32]:

array([[0, list([1]), 1.0],
       [list([1]), 0, 1.0],
       [list([1]), 0, 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), 0, 1.0],
       [list([1]), list([1]), 1.0]], dtype=object)

In [33]:

np.vstack((c1, c2, c3)).T

Out[33]:

array([[0, list([1]), 1.0],
       [list([1]), 0, 1.0],
       [list([1]), 0, 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), 0, 1.0],
       [list([1]), list([1]), 1.0]], dtype=object)

Это учитывает типы данных, хранящиеся в массиве. Однако, как только любой список, состоящий из идентичных массивов, добавляется в микс, это происходит:

In [28]:

c1 = [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
c2 = [[1], 0, 0, [1], [1], [1], [1], [1], 0, [1]]
c3 = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

In [29]:

np.c_[c1,c2,c3]

Out[29]:

array([[1, list([1]), 1.0],
       [1, 0, 1.0],
       [1, 0, 1.0],
       [1, list([1]), 1.0],
       [1, list([1]), 1.0],
       [1, list([1]), 1.0],
       [1, list([1]), 1.0],
       [1, list([1]), 1.0],
       [1, 0, 1.0],
       [1, list([1]), 1.0]], dtype=object)

In [30]:

np.vstack((c1, c2, c3)).T

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-30-b54eaf7a5522> in <module>
----> 1 np.vstack((c1, c2, c3)).T

<__array_function__ internals> in vstack(*args, **kwargs)

~/anaconda3/envs/idp/lib/python3.8/site-packages/numpy/core/shape_base.py in vstack(tup)
    280     if not isinstance(arrs, list):
    281         arrs = [arrs]
--> 282     return _nx.concatenate(arrs, 0)
    283 
    284 

<__array_function__ internals> in concatenate(*args, **kwargs)

ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 1 and the array at index 1 has size 10

Единственное различие между двумя кодовыми блоками состоит в том, что теперь список c1 полностью состоит из элементов [1] - используя np.c_ преобразует этот список в плоский список, я считаю, что это то, что нарушает и np.vstack (). Есть ли способ обойти это поведение?

Редактировать: Я имею в виду, есть ли в любом случае что-то эквивалентное этому:

array([[list([1]), list([1]), 1.0],
       [list([1]), 0, 1.0],
       [list([1]), 0, 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), list([1]), 1.0],
       [list([1]), 0, 1.0],
       [list([1]), list([1]), 1.0]], dtype=object)

, когда первый столбец полностью состоит из список идентичных элементов, будь то строки, списки или что-то еще.

1 Ответ

2 голосов
/ 13 февраля 2020

И c_, и vstack создают массивы из входов.

In [8]: c1 = [0, [1], [1], [1], [1], [1], [1], [1], [1], [1]] 
   ...: c2 = [[1], 0, 0, [1], [1], [1], [1], [1], 0, [1]] 
   ...: c3 = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]                                
In [9]: np.array(c1)                                                                           
Out[9]: 
array([0, list([1]), list([1]), list([1]), list([1]), list([1]),
       list([1]), list([1]), list([1]), list([1])], dtype=object)
In [10]: np.array(c2)                                                                          
Out[10]: 
array([list([1]), 0, 0, list([1]), list([1]), list([1]), list([1]),
       list([1]), 0, list([1])], dtype=object)
In [11]: np.array(c3)                                                                          
Out[11]: array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

Это все (10,) 1d массивы. Не так со следующей c1.

In [12]: c1 = [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]                               
In [13]: np.array(c1)                                                                          
Out[13]: 
array([[1],
       [1],
       [1],
       [1],
       [1],
       [1],
       [1],
       [1],
       [1],
       [1]])

np.vstack преобразует все входы в 2d массивы. То есть 1d массивы теперь имеют форму (1,10). Это concatenate на оси кулака для создания массива (3,10).

В последнем случае (10,1) нельзя объединить с массивами (1,10).

np.c_ выполняет более сложную настройку формы. Если коротко, то, что здесь происходит, - это преобразование всех массивов в форму (10,1) и конкатентация по 2-й оси. np.column_stack делает то же самое.

Или использует базовый concatenate:

np.concatenate([np.array(c1), np.array(c2)[:,None], np.array(c3)[:,None]],axis=1) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...