Как из двумерного массива сделать одномерный
Перейти к содержимому

Как из двумерного массива сделать одномерный

  • автор:

Переформатирование, изменение формы — Python: Numpy-массивы

Часто разработчикам приходится изменять размеры массивов. Например, переформатировать исходные данные, чтобы разделить их на подмассивы. В некоторых случаях требуется еще и объединять многомерные данные в единый массив значений. Чтобы решать такие задачи, массивы numpy.ndarray предоставляют набор методов, самым популярным из которых является метод reshape() .

В этом уроке разберем, как работать с размерами массивов numpy.ndarray и как получать их производные. Еще поговорим об ограничениях размерности и узнаем, как они помогают оптимизировать работу.

Как изменить размер массива

Представим, что нам нужно увеличить размер массива numpy.ndarray . Для этого будем идти по следующим шагам:

  1. Узнаем размер массива и индексы вдоль оси
  2. Изменим размер массива

Рассмотрим каждый этап подробнее.

Как узнать размер массива и индексы вдоль оси

Чтобы изменить размер numpy.ndarray , нужно узнать его значение. Для этого используют атрибут shape :

import numpy as np one_dimension_array = np.array( [0,1,2,3,4,5,6,7,8,9,10,11] ) print(one_dimension_array.shape) # => (12,) two_dimensions_array = np.array( [ [0,1,2], [3,4,5], [6,7,8], [9,10,11] ] ) print(two_dimensions_array.shape) # => (4, 3) three_dimensions_array = np.array( [ [ [0,1], [2,3], ], [ [4,5], [6,7], ], [ [8,9], [10,11] ] ] ) print(three_dimensions_array.shape) # => (3, 2, 2) 

В примере выше атрибут shape возвращает кортеж целых чисел. Длина кортежа указывает на размерность массива:

  • (12,) — одномерный массив
  • (4, 3) — двумерный массив
  • (3, 2, 2) — трехмерный массив

Числа в кортеже означают количество элементов по конкретной оси индексов:

  • (12,) — 12 значений
  • (4, 3) — четыре блока значений по три значения в каждом
  • (3, 2, 2) — три блока значений, каждый из которых состоит из двух блоков по два значения

Название ось индексов отсылает к декартовой системе координат. Вспомним ее основные правила:

  • Чтобы построить отрезок или другой одномерный объект, достаточно одной координатной оси
  • Чтобы построить квадрат или другой двумерный объект, необходима координатная плоскость из двух перпендикулярных осей
  • Чтобы построить куб или другой трехмерный объект, нужно три ортогональные оси координат

Теперь, когда мы знаем размер исходного массива, можно изменять его форму. Для этого используем метод reshape() .

Как изменить размер массива с помощью метода reshape()

В Python используется метод reshape() , с помощью которого можно получить двухмерный и трехмерный массив из одномерного. Этот обязательный параметр ожидает новый размер данных, к которому нужно переформатировать исходный массив.

Попробуем получить двумерный массив two_dimensions_array из одномерного массива one_dimension_array . Для этого используем метод reshape() с новым размером данных (4, 3) :

print(one_dimension_array.reshape((4, 3))) # => [[ 0 1 2] # [ 3 4 5] # [ 6 7 8] # [ 9 10 11]] 

Чтобы получить трехмерный массив three_dimensions_array , достаточно также указать нужный размер:

print(one_dimension_array.reshape((3, 2, 2))) # => [[[ 0 1] # [ 2 3]] # [[ 4 5] # [ 6 7]] # [[ 8 9] # [10 11]]] 

Изменять форму массива можно не только от данных меньшей размерности к данным большей размерности. Это можно делать и в обратную сторону.

Попробуем получить исходный одномерный массив one_dimension_array из двумерного массива two_dimensions_array :

print(two_dimensions_array.reshape((12,))) # => [ 0 1 2 3 4 5 6 7 8 9 10 11] 

А тут переформатируем three_dimensions_array в two_dimensions_array :

print(three_dimensions_array.reshape((4,3))) # => [[ 0 1 2] # [ 3 4 5] # [ 6 7 8] # [ 9 10 11]] 

Необязательно уменьшать размер последовательно. Например, можно из трехмерного массива получить сразу одномерный:

print(three_dimensions_array.reshape((12,))) # => [ 0 1 2 3 4 5 6 7 8 9 10 11] 

С помощью атрибута shape можно узнать размерность массива numpy.ndarray . А метод reshape поможет ее уменьшить или увеличить. Однако у этого массива есть ограничения по размеру данных — его нужно соблюдать, чтобы оптимизировать выполнения методов над массивами.

Какие размеры массива допустимы

У массива numpy.ndarray есть ограничения по размеру данных — по осям индексов должны быть данные одного размера. Это ограничение позволяет оптимизировать выполнения методов над массивами. Рассмотрим на примере.

Допустим, нам нужно сконвертировать список из списков длиной три и два:

np.array( [ [0,1,2], [3,4,], ] ) # => [list([0, 1, 2]) list([3, 4])] 

На первый взгляд у нас получился массив numpy.ndarray . Но если внимательно посмотреть на элементы, мы увидим, что получились списки, а не ожидаемые целочисленные массивы. Это ограничит дальнейшую работу с данными, потому что поведение многих методов меняется.

Попробуем найти в данном массиве максимальный элемент 4 . Это приведет к такому результату:

print(np.array( [ [0,1,2], [3,4,], ] ).max()) # => [3, 4] 

В этом примере мы получили не тот результат, которого ожидали.

Numpy старается предотвращать некорректные действия — для этого в нем есть система предупреждений и подсказок. Но это не значит, что не нужно следить за размером массива. Он играет важную роль в реализации методов библиотеки Numpy, поэтому рекомендуем обращать внимание на этот момент.

В случае с методом reshape() Numpy вообще не дает совершить некорректную конвертацию массива из 12 элементов в массив из 15 элементов — три блока по пять значений. В этом случае он вызывает исключение:

one_dimension_array.reshape(3,5) # => ValueError: cannot reshape array of size 12 into shape (3,5) 

Ограничения по размеру могут добавить неудобств, когда мы увеличиваем или уменьшаем размерность массива. При этом они позволяют не указывать некоторые значения размера, когда мы хотим его изменить.

Как сделать автоматический расчет размера массива

Ограничения на размер массива позволяют не указывать некоторые размеры в методе reshape() . Это можно оставить на автоматический расчет. Для этого нужное значение размерности поменяем на -1 :

print(one_dimension_array.reshape((4,3))) print(one_dimension_array.reshape(((4, -1)))) print(one_dimension_array.reshape(((-1, 3)))) # => [[ 0 1 2] # [ 3 4 5] # [ 6 7 8] # [ 9 10 11]] 

Все преобразования в примере выше дают одинаковый результат. Необходимый размер рассчитывается автоматически, исходя из количества элементов.

Для массивов большей размерности это работает по такому же принципу:

print(one_dimension_array.reshape((3, 2, 2))) print(one_dimension_array.reshape((-1, 2, 2))) print(one_dimension_array.reshape((3, -1, 2))) print(one_dimension_array.reshape((3, 2, -1))) # => [[[ 0 1] # [ 2 3]] # [[ 4 5] # [ 6 7]] # [[ 8 9] # [10 11]]] 

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

print(three_dimensions_array.reshape((12,))) print(three_dimensions_array.reshape((-1,))) # => [ 0 1 2 3 4 5 6 7 8 9 10 11] 

Теперь вы знаете, как определять размерность массива. Вы умеете изменять размер и рассчитывать его автоматически. Чтобы закрепить знания на практике, рассмотрим еще один пример.

Как размер массива меняется на практике

Изменение формы массива помогает подготовить исходные данные — после такой обработки их будет удобнее анализировать и преобразовывать.

Представим сервис платформы продаж, который логирует данные по сетевым магазинам в конце рабочего дня в определенном порядке. Аналитики выгрузили данные из закрытого контура платформы. Так они получили 28 значений подневных продаж сети:

orders = [7, 1, 7, 8, 4, 2, 4, 5, 3, 5, 2, 3, 8, 12, 8, 7, 15, 11, 13, 9, 21, 18, 17, 21, 25, 16, 25, 17,] shops_number = 4 orders_matrix = np.array(orders) orders_matrix = orders_matrix.reshape(-1, shops_number) print(orders_matrix) # => [[ 7 1 7 8] # [ 4 2 4 5] # [ 3 5 2 3] # [ 8 12 8 7] # [15 11 13 9] # [21 18 17 21] # [25 16 25 17]] print(orders_matrix.shape) # => (7, 4) 

Полученный массив данных можно визуализировать в виде такой таблицы:

День Магазин №1 Магазин №2 Магазин №3 Магазин №4
0 7 1 7 8
1 4 2 4 5
2 3 5 2 3
3 8 12 8 7
4 15 11 13 9
5 21 18 17 21
6 25 16 25 17

Выводы

Метод shape — важный атрибут для структурного описания массива numpy.ndarray . Он помогает узнать размер вдоль каждой оси.

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Запись двумерного массива в одномерный python

Красиво сделал, я думал также только я писал справа на лево, и мне писало что оно хз что такое b. Красавчик.

13 мая 2021 в 14:51

matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] print(sum(matrix, [])) 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] 

Отслеживать
ответ дан 18 сен 2021 в 14:47
андрей шадрин андрей шадрин
51 1 1 серебряный знак 3 3 бронзовых знака

добро пожаловать на Stack Overflow на русском! пожалуйста, постарайтесь оставлять чуть более развёрнутые ответы. дополнить ответ можно, нажав править

18 сен 2021 в 14:48

Вот пример кода:

l = [elem[0] for elem in l] 

Если во вложенных списка больше 1 элемента то так:

answer = [] for i in l: answer.append(i) 

Отслеживать
ответ дан 17 мая 2020 в 9:28
BigCubeCat BigCubeCat
740 7 7 серебряных знаков 20 20 бронзовых знаков

Преобразование двумерного массива в одномерный:

arr = [[2, 0, 0], [3, 0, 9], [4, 7, 6], [5, 1, 3]] x = len(arr[0]) y = len(arr) lst = [] for i in range(y): for j in arr[i]: lst.append(j) lst 
[2, 0, 0, 3, 0, 9, 4, 7, 6, 5, 1, 3] 

Отслеживать
ответ дан 2 апр 2021 в 11:59
466 1 1 золотой знак 6 6 серебряных знаков 20 20 бронзовых знаков

l = [[2], [3], [4], [5]] l = list((np.array(l)).reshape(4,)) 

Отслеживать
1,811 1 1 золотой знак 5 5 серебряных знаков 23 23 бронзовых знака
ответ дан 3 фев 2022 в 7:45
Михаил Титов Михаил Титов
1 1 1 бронзовый знак

добро пожаловать на Stack Overflow на русском! пожалуйста, постарайтесь оставлять чуть более развёрнутые ответы. дополнить ответ можно, нажав править

3 фев 2022 в 7:46

У numpy есть методы «выпрямления» массивов без указания конкретного размера: ravel() и flatten() . Ну и использовать numpy тут как из пушки по воробьям. )

3 фев 2022 в 8:26
А без numpy в несколько строчек расписывать циклом лучше?
4 фев 2022 в 9:44

для превращения многомерного массива я предлагаю использовать функцию

my_list = [1, [2, 3], ["four", [5, "6"]], []] to_line(my_list) 
def to_line(arr: list): out = [] for i in arr: if isinstance(i, list): tl_arr = to_line(i) for j in tl_arr: out.append(j) else: out.append(i) return out 
[1, 2, 3, "four", 5, "6"] 

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

Как из двумерного массива сделать одномерный

Крайне рекомендую хотя бы переписать код(Не ctrl+C -> ctrl+V, а ручками), где создается шахматное поле, до прочтения статьи не было совсем ясно, как класть разные буквы и цифры в нужные ячейки массива. Спасибо за открытие этого метода:

 Character.toString(letters.charAt(a)) 

Про перемножение матриц и задачи с многомерными массивами, пока не понял, но в закладки добавил �� Уже выработалось понимание, «Если в этот раз непонятно, то просто прочти до конца, а потом посмотри на это под другим углом» Когда-то я не понимал самих массивов��

Владислав Уровень 16
26 февраля 2023

перемножение матриц бошку вынесло, когда попытался представить написанный код)) короче если мне попадется такая задача, я сначало залезу в википедию, чтобы лучше понять) И это при условии, что я сдавал линейную алгебру в универе, прошло с тех пор 15 лет — я забыл 90%!

18 февраля 2023

Пришлось вспоминать как работают матрицы. А ведь я и подумать не мог, что после экзамена ещё хоть раз в жизни их увижу. Кстати, спасибо за пример с парковкой��

Kergshi Уровень 20
9 февраля 2023

Если у кого возникнет вопрос в примере вывода шахматной доски с с нумерацией ячеек,да! Вы правильно подумали,да,можно выбросить к черту повтор 2-х циклов ,а выводы сразу первых двух писать и будет работать точно также. Конечно,может я еще глуп и эта абра-кадабра с повторением одного и того же имеет смысл,но так как объяснения этому нет,то я «лишнее» выкинул и всё так же в итоге осталось по работоспособности.

Kergshi Уровень 20
9 февраля 2023

Просвятите,пожалуйста,почему второй пример с доской,если скопировать, не работает в идее,выдаёт 15 ошибок. Циклы for вообще за циклы не воспринимает.

Kergshi Уровень 20
25 января 2023

Да как разобраться во всей это куче ссылок. Идешь просто по курсу и тут на тебе,100500 ссылок почить то,почитать это. А там еще штук пять. Тут просто массивы,там «кое-что о массивах»,»массивы в Java». С ума сойти можно

Kirill Уровень 22
25 декабря 2022

Как раз ищу ответ на это высказывание: «Если мы имеем дело с прямоугольными двумерными массивами (то есть такими, у которых все строки одинаковой длины), то можно применить операцию twoDimArray[0].length или вместо нулевого элемента (по сути — нулевой строки) — любой другой существующий. Мы можем так поступить, потому что в Java двумерный массив — это массив массивов, и нулевой элемент twoDimArray[0] — это массив длины 4. Можете проверить это самостоятельно.» Что они имеют ввиду? Не вижу связи. Почему 0, а не [I]? Подскажите!

Олег Уровень 111 Expert
12 декабря 2022
Здравствуйте. Похоже в строке a[1][0]*b[0][0] + a[1][1]*b[0][1] + … + a[0][m-1]*b[m-1][0] ошибка.
Denis Odesskiy Уровень 34
11 декабря 2022

Здравствуйте! Не могу понять зачем в листинге с примером про шахматную доску перед выводом результата в консоль повторен этот цикл:

 for (int i = 0; i < chessBoard.length; i++) < for (int j = 0; j < chessBoard[0].length; j++)  

С ним у меня пример не работает, а без него работает, это опечатка? Или в чем моя ошибка? Вот мой листинг кода без этого цикла:

 public class CheessBoard < public static String cheessBoardCoord(int a, int b) < String letters = "abcdefgh"; String numbers = "87654321"; if ((a >7) || (b > 7)) return null; //если номер за пределами доски, возвращаем значение по умолчанию - null else return (Character.toString(letters.charAt(a)) + numbers.charAt(b)); /*charAt - метод, с помощью которого мы извлекаем из строки элемент под переданным номером, здесь - под номерами a и b. Character.toString - метод, который переводит полученный символ в строку*/ > public static void main(String[] args) < //задаём шахматную доску двумерным массивом String[][] cheessBoard = new String[8][8]; for (int i = 0; i < cheessBoard.length; i++) < for (int j = 0; j < cheessBoard[0].length; j++) < if ((i + j) % 2 == 0) cheessBoard[i][j] = "W" + cheessBoardCoord(j, i); else cheessBoard[i][j] = "B" + cheessBoardCoord(j, i); System.out.print(" " + cheessBoard[i][j] + " "); >System.out.println(); > > > 

В примере с умножением матриц ошибка, - не объявлен тип переменной k:

 for (k=0; k 

Как преобразовать многомерный php массив в одномерный

Самый простой вариант, это использовать встроенную в PHP функцию array_walk_recursive() , которая рекурсивно применяет колбек к каждому элементу массива:

 $collection = [['hexlet', ['is', 'awesome']], ['1', 2], [3, [4, 5, 6]]]; $result = []; array_walk_recursive($collection, function($item) use (&$result)  $result[] = $item >); print_r($result); // => Array // => ( // => [0] => hexlet // => [1] => is // => [2] => awesome // => [3] => 1 // => [4] => 2 // => [5] => 3 // => [6] => 4 // => [7] => 5 // => [8] => 6 // => ) 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *