Заполнение массивов в NumPy с помощью функций. Типы данных
Создано: 17.11.2025
В данном уроке будут рассмотрены функции array, arange, linspace, zeros, ones и empty библиотеки NumPy, с помощью которых создаются экземпляры ndarray (массивы) и происходит их заполнение определенными значениями. Заполнение случайными числами будет изучаться позже, как и создание двумерных и многомерных массивов. Вместо этого здесь уделим внимание типам данных элементов, которыми заполняются массивы NumPy.
Создание одномерных массивов и их заполнение заданными значениями
Самым очевидным способом создания массива является вызов функции array() и передача ей любой последовательности Python с явно заданными значениями элементов:
import numpy as np a = np.array([10.55, 12.78, 3, -4, 5.1]) b = np.array(('hello', 'world', 'ocean', 'planet')) c = np.array(range(100, 120, 3)) print(a, type(a)) print(b, type(b)) print(c, type(c))
[10.55 12.78 3. -4. 5.1 ] <class 'numpy.ndarray'> ['hello' 'world' 'ocean' 'planet'] <class 'numpy.ndarray'> [100 103 106 109 112 115 118] <class 'numpy.ndarray'>
Так в примере выше в array() передается список, кортеж и объект range, и независимо ни от этого, ни от типов содержащихся в них данных всегда создаются экземпляры ndarray — массивы NumPy. Функция не принимает "голые значения" за исключением случая, когда передается только одно:
a = np.array(1024) print(a, type(a))
1024 <class 'numpy.ndarray'>
Тогда создается массив с так называемой нулевой размерностью (даже не одномерный).
В первом примере мы передаем в функцию array() библиотеки NumPy экземпляр, созданный встроенной функцией range() языка Python. Однако делать так нет необходимости, поскольку в самом NumPy есть функция arange, которая вызывается вместо array(). Она также возвращает экземпляр ndarray, заполненный согласно переданному в нее диапазону.
a = np.arange(10) b = np.arange(-5, 3) c = np.arange(10, 1, -1) d = np.arange(0.5, 3) e = np.arange(0.54, 1.7, 0.21) print(f'{a}\n{b}\n{c}\n{d}\n{e}')
[0 1 2 3 4 5 6 7 8 9] [-5 -4 -3 -2 -1 0 1 2] [10 9 8 7 6 5 4 3 2] [0.5 1.5 2.5] [0.54 0.75 0.96 1.17 1.38 1.59]
В отличие от range() в arange() можно передавать вещественные числа. Но это не очень удобно, так как трудно понять сколько всего будет значений в массиве. Когда нужно точно задать количество элементов, вместо arange лучше подходит linspace. Однако здесь уже не задается шаг, разница между соседними значениями вычисляется, исходя из количества элементов и диапазона. Можно сказать, отрезок нарезается на равные части.
a = np.linspace(-6, 7, 4) b = np.linspace(0.1, 1.7, 5) print(a) print(b)
[-6. -1.66666667 2.66666667 7. ] [0.1 0.5 0.9 1.3 1.7]
Обратим внимание, что в случае linspace верхняя граница входит в диапазон, что логично.
Если массив надо заполнить только нулями или только единицами, то это делается вызовом функций zeros() или ones().
a = np.zeros(10) b = np.ones(10) print(a) print(b)
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
Точки в выводе выше — это не разделители между элементами, а указание на дробность чисел. Как заполнить массив другими типами данных, будет сказано ниже.
Наконец, остановимся на функции empty. Она создает массив заданной размерности, но ничем его не заполняет. Однако в занятых под массив ячейках памяти уже содержатся те или иные значения (могут и нули), поэтому массив оказывается не столько пустым, сколько заполненным "мусором".
a = np.empty(3) print(a)
[6.70315468e-310 2.91923454e-315 6.70315297e-310]
Случайные данные, которыми инициируется массив, не надо путать с заполнением случайными числами. Во втором случае мы как минимум указываем диапазон возможных значений.
Типы данных NumPy
Отличие истинных массивов от списков Python заключается не только в скорости их обработки (с массивами это происходит куда быстрее). Также важно, что количество элементов в массиве должно оставаться постоянным, а все значения быть одного типа.
Если мы извлечем отдельный элемент (в случае с одномерными массивами делается это также как со списками) и посмотрим его тип, то несколько удивимся:
a = np.array([10.55, 12.78, 3, -4, 5.1]) print(a[0], type(a[0])) print(a[-2], type(a[-2]))
10.55 <class 'numpy.float64'> -4.0 <class 'numpy.float64'>
Вместо типа float языка Python в NumPy используется тип float64. Кроме того, из примера видно, что целое число -4 было преобразовано в этот тип. Если бы был задан смешанный список чисел и строк, то все значения были бы преобразованы в строку. Чтобы получить массив целых чисел, все входные значения должны быть таковыми.
a = np.array([10, 'hello', 3, -4, 5]) b = np.array([10, 12, 3, -4, 5]) print(a, type(a[0])) print(b, type(b[0]))
['10' 'hello' '3' '-4' '5'] <class 'numpy.str_'> [10 12 3 -4 5] <class 'numpy.int64'>
У экземпляров ndarray есть свойство dtype, позволяющее посмотреть тип данных составляющих массив элементов:
a = np.arange(1, 5) b = np.linspace(0, 2, 6) c = np.array(['yes', 'no']) d = np.array(['Moscow', 'New York']) e = np.array(['правда', 'ложь']) print(a, a.dtype) print(b, b.dtype) print(c, c.dtype) print(d, d.dtype) print(e, e.dtype)
[1 2 3 4] int64 [0. 0.4 0.8 1.2 1.6 2. ] float64 ['yes' 'no'] <U3 ['Moscow' 'New York'] <U8 ['правда' 'ложь'] <U6
Как мы видим, строковый тип данных конкретизируется: показывается, сколько символов юникод отводится под каждый элемент. Размер определяется самой длинной строкой.
С другой стороны, функции создания и заполнения массивов в NumPy имеют одноименный параметр dtype, с помощью которого можно указать желаемый тип данных.
a = np.arange(1, 50, 15, dtype='i2') b = np.linspace(1, 50, 6, dtype=int) c = np.linspace(1, 50, 6, dtype='f4') d = np.linspace(1, 50, 6, dtype=float) e = np.array(['правда', 'ложь'], dtype='U10') f = np.ones(5, dtype='i1') print(a, a.dtype) print(b, b.dtype) print(c, c.dtype) print(d, d.dtype) print(e, e.dtype) print(f, f.dtype)
[ 1 16 31 46] int16 [ 1 10 20 30 40 50] int64 [ 1. 10.8 20.6 30.4 40.2 50. ] float32 [ 1. 10.8 20.6 30.4 40.2 50. ] float64 ['правда' 'ложь'] <U10 [1 1 1 1 1] int8
Присваивать dtype python-классы int, float и другие имеет смысл, если вы хотите поменять только тип данных. Если есть желание сэкономить память, то следует использовать буквы-спецификации с указанием после них количества байтов (при выводе числовых типов данных показывается число битов, так 'i2' соответствует int16). Список допустимых в NumPy типов: i — целое число, b — булево значение, u — беззнаковое целое, f — вещественное число, c — комплексное число, m — timedelta (промежуток времени), M — datetime (дата и время), O — объект, S — строка, U — юникод-строка, V — фиксированный фрагмент памяти для других типов (void).
У numpy-массивов есть метод astype, который создает копию существующего массива, но с элементами другого типа. Таким образом, в процессе выполнения программы можно поменять тип данных элементов массива, если в этом возникает необходимость.
a = np.empty(4, dtype='i') print(a) a = a.astype('u1') print(a) b = a.astype(bool) print(b)
[ 0 -1073741824 -881360897 32500] [ 0 0 255 244] [False False True True]