Numpy append: автоматически накладывать массив неправильного измерения

есть ли способ сделать следующее без предложения if?

Я читаю набор файлов netcdf с pupynere и хочу построить массив с numpy append. Иногда входные данные многомерны (см. Ниже «a»), иногда одномерное («b»), но количество элементов в первом измерении всегда одно и то же («9» в примере ниже).

  • загружаемые массивы, сохраненные с помощью numpy.save в режиме добавления
  • Python: List append () in для цикла
  • Почему append не возвращает ничего в этом коде?
  • > import numpy as np > a = np.arange(27).reshape(3,9) > b = np.arange(9) > a.shape (3, 9) > b.shape (9,) 

    это работает так, как ожидалось:

     > np.append(a,a, axis=0) array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 9, 10, 11, 12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23, 24, 25, 26], [ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 9, 10, 11, 12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23, 24, 25, 26]]) 

    но добавление b не работает так элегантно:

     > np.append(a,b, axis=0) ValueError: arrays must have same number of dimensions 

    Проблема с append (из руководства numpy)

    «Когда указана ось, значения должны иметь правильную форму».

    Я должен был сделать первый, чтобы получить правильный результат.

     > np.append(a,b.reshape(1,9), axis=0) array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 9, 10, 11, 12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23, 24, 25, 26], [ 0, 1, 2, 3, 4, 5, 6, 7, 8]]) 

    Итак, в моем цикле чтения файла я в настоящее время использую предложение if, подобное этому:

     for i in [a, b]: if np.size(i.shape) == 2: result = np.append(result, i, axis=0) else: result = np.append(result, i.reshape(1,9), axis=0) 

    Есть ли способ добавить «a» и «b» без инструкции if?

    EDIT: В то время как @Sven отлично ответил на исходный вопрос (используя np.atleast_2d() ), он (и другие) указал, что код неэффективен. В ответе ниже я объединил их предложения и заменил мой оригинальный код. Теперь он должен быть намного более эффективным. Благодарю.

  • загружаемые массивы, сохраненные с помощью numpy.save в режиме добавления
  • Python: List append () in для цикла
  • Почему append не возвращает ничего в этом коде?
  • 4 Solutions collect form web for “Numpy append: автоматически накладывать массив неправильного измерения”

    Вы можете использовать numpy.atleast_2d() :

     result = np.append(result, np.atleast_2d(i), axis=0) 

    Тем не менее, обратите внимание, что повторное использование numpy.append() – очень неэффективный способ построения массива NumPy – он должен быть перераспределен на каждом шаге. Если это вообще возможно, предварительно распределите массив с требуемым конечным размером и заполните его потом, используя нарезку.

    Вы можете просто добавить все массивы в список, а затем использовать np.vstack() чтобы объединить их все вместе в конце. Это позволяет избежать перераспределения растущего массива с каждым добавлением.

     |1> a = np.arange(27).reshape(3,9) |2> b = np.arange(9) |3> np.vstack([a,b]) array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 9, 10, 11, 12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23, 24, 25, 26], [ 0, 1, 2, 3, 4, 5, 6, 7, 8]]) 

    Я собираюсь улучшить свой код с помощью @Sven, @Henry и @Robert. @Sven ответил на вопрос, поэтому он заслужил репутацию этого вопроса, но, как подчеркнул он и другие, есть более эффективный способ делать то, что я хочу.

    Это связано с использованием списка python, который позволяет добавлять с ограничением производительности O (1), тогда как numpy.append () имеет ограничение производительности O (N ** 2) . После этого список преобразуется в массив numpy:

    Предположим, что i является либо типом a либо b :

     > a = np.arange(27).reshape(3,9) > b = np.arange(9) > a.shape (3, 9) > b.shape (9,) 

    Инициализируйте список и добавьте все прочитанные данные, например, если данные отображаются в порядке «aaba».

     > mList = [] > for i in [a,a,b,a]: mList.append(i) 

    Ваш mList будет выглядеть так:

     > mList [array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 9, 10, 11, 12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23, 24, 25, 26]]), array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 9, 10, 11, 12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23, 24, 25, 26]]), array([0, 1, 2, 3, 4, 5, 6, 7, 8]), array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 9, 10, 11, 12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23, 24, 25, 26]])] 

    наконец, vstack список, чтобы сформировать массив numpy:

     > result = np.vstack(mList[:]) > result.shape (10, 9) 

    Еще раз спасибо за ценную помощь.

    Как указано, append необходимо перераспределить каждый массив numpy. Альтернативное решение, которое выделяет один раз, будет примерно таким:

     total_size = 0 for i in [a,b]: total_size += i.size result = numpy.empty(total_size, dtype=a.dtype) offset = 0 for i in [a,b]: # copy in the array result[offset:offset+i.size] = i.ravel() offset += i.size # if you know its always divisible by 9: result = result.reshape(result.size//9, 9) 

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

     result = result[0:known_final_size] 
    Python - лучший язык программирования в мире.