2016-03-15 3 views
9

В numpy размеры результирующего массива меняются во время выполнения. Часто возникает путаница между массивом 1d и 2d массивом с 1 столбцом. В одном случае я могу перебирать столбцы, в другом случае я не могу.Numpy reshape 1d to 2d array with 1 column

Как вы решительно решаете эту проблему? Чтобы избежать замусоривания программы if заявления проверки размерности, я использую эту функцию:

def reshape_to_vect(ar): 
    if len(ar.shape) == 1: 
     return ar.reshape(ar.shape[0],1) 
    return ar 

Однако это чувствует безвкусный и дорогостоящим. Есть ли лучшее решение?

+0

Что такое 'dtype'? Выглядит «структурировано». – hpaulj

+0

Это не имеет значения, я просто использовал это как пример того, как я мог бы получить массив 1d или 2d. Мой вопрос о том, как систематически преобразовывать 1d в 2d-массив. – DevShark

ответ

7

Вы могли бы сделать -

ar.reshape(ar.shape[0],-1) 

Это второй вход reshape: -1 заботится о количестве элементов для второй оси. Таким образом, для входного регистра 2D он не изменяется. Для ввода ввода 1D он создает массив 2D со всеми элементами, которые «нажимаются» на первую ось из-за ar.shape[0], что было общим количеством элементов.

Sample работает

1D Корпус:

In [87]: ar 
Out[87]: array([ 0.80203158, 0.25762844, 0.67039516, 0.31021513, 0.80701097]) 

In [88]: ar.reshape(ar.shape[0],-1) 
Out[88]: 
array([[ 0.80203158], 
     [ 0.25762844], 
     [ 0.67039516], 
     [ 0.31021513], 
     [ 0.80701097]]) 

2D Case:

In [82]: ar 
Out[82]: 
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523], 
     [ 0.39728524, 0.03952238, 0.04153052, 0.82009233], 
     [ 0.38748174, 0.51377738, 0.40365096, 0.74823535]]) 

In [83]: ar.reshape(ar.shape[0],-1) 
Out[83]: 
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523], 
     [ 0.39728524, 0.03952238, 0.04153052, 0.82009233], 
     [ 0.38748174, 0.51377738, 0.40365096, 0.74823535]]) 
+1

Вариант этого ответа: 'x = np.reshape (x, (len (x), - 1))', который также относится к случаю, когда вход представляет собой список 1d или 2d. –

+0

@LucaCiti сделать это отдельным ответом, чтобы я мог его проголосовать. –

+0

Готово. Спасибо за вашу рекомендацию. –

0

Я спросил о dtype, потому что ваш пример озадачивает.

я могу сделать структурированный массив с 3-х элементов (1d) и 3-х полей:

In [1]: A = np.ones((3,), dtype='i,i,i') 
In [2]: A 
Out[2]: 
array([(1, 1, 1), (1, 1, 1), (1, 1, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')]) 

я могу получить доступ к одному полю по имени (добавляющие скобки не меняет дела)

In [3]: A['f0'].shape 
Out[3]: (3,) 

но если я получаю 2 поля, я все равно получаю 1-й массив

In [4]: A[['f0','f1']].shape 
Out[4]: (3,) 
In [5]: A[['f0','f1']] 
Out[5]: 
array([(1, 1), (1, 1), (1, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 

На самом деле эти дополнительные скобки имеют значение, если я loo K при значениях

In [22]: A['f0'] 
Out[22]: array([1, 1, 1], dtype=int32) 
In [23]: A[['f0']] 
Out[23]: 
array([(1,), (1,), (1,)], 
     dtype=[('f0', '<i4')]) 

Если массив простой 2d один, я до сих пор не получают свои формы

In [24]: A=np.ones((3,3),int) 
In [25]: A[0].shape 
Out[25]: (3,) 
In [26]: A[[0]].shape 
Out[26]: (1, 3) 
In [27]: A[[0,1]].shape 
Out[27]: (2, 3) 

Но на вопрос о убедившись, что массив является 2d, независимо от того, индексация возвращает 1d или 2, ваша функция в основном нормально

def reshape_to_vect(ar): 
    if len(ar.shape) == 1: 
     return ar.reshape(ar.shape[0],1) 
    return ar 

Вы можете проверить ar.ndim вместо len(ar.shape). Но в любом случае это не дорого - то есть время выполнения минимально - никаких больших операций массива. reshape не копирует данные (если только ваши шаги не странны), поэтому это просто затраты на создание нового объекта массива с общим указателем данных.

Посмотрите на код для np.atleast_2d; он тестирует 0d и 1d. В 1-м случае он возвращает result = ary[newaxis,:]. Он добавляет дополнительную ось сначала, более естественное местоположение для добавления оси. Вы добавляете его в конце.

ar.reshape(ar.shape[0],-1) - это умный способ обхода теста if. В небольших временных тестах это происходит быстрее, но мы говорим о микросекундах, о влиянии слоя вызова функции.

np.column_stack - еще одна функция, которая при необходимости создает столбчатые массивы. Он использует:

if arr.ndim < 2: 
     arr = array(arr, copy=False, subok=True, ndmin=2).T 
+0

Хорошо, я удалил пример. Я пытался дать конкретный пример, но если это сбивает с толку, лучше не иметь его. – DevShark

0

Чтобы избежать необходимости, чтобы изменить в первую очередь, если вы отрезаете строку/столбец со списком, или кусочек «работает», вы получите 2D массив с одной строки/столбца

import numpy as np 
x = np.array(np.random.normal(size=(4,4))) 
print x, '\n' 

Result: 
[[ 0.01360395 1.12130368 0.95429414 0.56827029] 
[-0.66592215 1.04852182 0.20588886 0.37623406] 
[ 0.9440652 0.69157556 0.8252977 -0.53993904] 
[ 0.6437994 0.32704783 0.52523173 0.8320762 ]] 

y = x[:,[0]] 
print y, 'col vector \n' 
Result: 
[[ 0.01360395] 
[-0.66592215] 
[ 0.9440652 ] 
[ 0.6437994 ]] col vector 


y = x[[0],:] 
print y, 'row vector \n' 

Result: 
[[ 0.01360395 1.12130368 0.95429414 0.56827029]] row vector 

# Slice with "running" index on a column 
y = x[:,0:1] 
print y, '\n' 

Result: 
[[ 0.01360395] 
[-0.66592215] 
[ 0.9440652 ] 
[ 0.6437994 ]] 

Вместо если вы используете один номер для выбора строки/столбца, это приведет к 1D массив, который является основной причиной вашего вопроса:

y = x[:,0] 
print y, '\n' 

Result: 
[ 0.01360395 -0.66592215 0.9440652 0.6437994 ] 
2

Вариант ответа от divakar: x = np.reshape(x, (len(x),-1)), который также касается случая, когда вход является 1d или 2d списком.