Нашли ошибку?
продвинутыйNumPy 2.5.3

Структурированные массивы

Массив записей с именованными полями разных типов — как таблица, но в одном массиве NumPy.

Нужно знать:Типы данных и astypeБулевы маски

Содержание статьи

Коротко

  • Тип элемента задаётся списком полей: np.dtype([("name", "U10"), ("age", "i4")]). Каждый элемент — запись.
  • a["age"] — массив одного поля (представление); a[1] — одна запись.
  • Работают маски, сортировка по полю (order="age"), запись в поле.
  • Полезно для чтения двоичных форматов и обмена с C-кодом. Для анализа табличных данных почти всегда удобнее pandas DataFrame.

Синтаксис

dt = np.dtype([("name", "U10"), ("age", "i4"), ("score", "f8")])
a = np.array([("Аня", 21, 4.5), ...], dtype=dt)   # элементы — кортежи
a["age"]                  # поле
a[0]                      # запись
np.sort(a, order="age")
Код типа Значение
"U10" строка до 10 символов
"i4", "i8" целое 4 / 8 байт
"f8" float64
"?" bool

Примеры

Данные для примеровиспользуются во всех примерах ниже
student = np.dtype([("name", "U10"), ("age", "i4"), ("score", "f8")])
people = np.array([("Аня", 21, 4.5),
                   ("Борис", 19, 3.8),
                   ("Вика", 22, 4.9)], dtype=student)
Массив записей
print(people.dtype)
people
Вывод
[('name', '<U10'), ('age', '<i4'), ('score', '<f8')]
array([('Аня', 21, 4.5), ('Борис', 19, 3.8), ('Вика', 22, 4.9)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('score', '<f8')])
Поле как массив
print(people["name"])
people["score"].mean()
Вывод
['Аня' 'Борис' 'Вика']
np.float64(4.4)
Одна запись
print(people[1])
people[1]["age"]
Вывод
('Борис', 19, 3.8)
np.int32(19)
Фильтр по полю
people[people["score"] > 4]["name"]
Вывод
array(['Аня', 'Вика'], dtype='<U10')
Сортировка по полю
np.sort(people, order="age")["name"]
Вывод
array(['Борис', 'Аня', 'Вика'], dtype='<U10')
Изменить поле
people["age"] += 1
people["age"]
Вывод
array([22, 20, 23], dtype=int32)

Подводные камни

Строки фиксированной длины

Поле "U10" хранит не больше 10 символов: длинные значения молча обрезаются. Выбирайте длину с запасом.

Длинное имя
people["name"][0] = "Александра-Мария"    # 16 символов в поле U10
people["name"]
Вывод
array(['Александра', 'Борис', 'Вика'], dtype='<U10')

Для таблиц есть pandas

Группировка, объединение, пропуски и работа со строками в структурированных массивах неудобны. Массив легко превратить в DataFrame.

Структурированный массив в DataFrame
pd.DataFrame(people)                    # для анализа таблиц удобнее pandas
Вывод
    name  age  score
0    Аня   21    4.5
1  Борис   19    3.8
2   Вика   22    4.9