Что такое двумерный массив (матрица)?
Двумерный массив, или матрица, представляет собой структуру данных, организованную в виде строк и столбцов. Каждый элемент в матрице идентифицируется двумя индексами: номером строки и номером столбца. Матрицы широко используются для представления табличных данных, изображений (где каждый элемент представляет собой пиксель), а также для математических вычислений, например, в линейной алгебре.
Преимущества использования NumPy для работы с массивами
NumPy (Numerical Python) — это мощная библиотека Python, предназначенная для эффективной работы с массивами, особенно с многомерными. Основные преимущества использования NumPy:
- Эффективность: NumPy массивы хранятся в памяти более компактно, чем стандартные списки Python, и операции над ними выполняются значительно быстрее.
- Функциональность: NumPy предоставляет широкий набор функций для математических операций, линейной алгебры, преобразования массивов и многого другого.
- Удобство: Синтаксис NumPy делает работу с массивами интуитивно понятной и простой.
- Интеграция: NumPy легко интегрируется с другими библиотеками Python для анализа данных, такими как SciPy, pandas и scikit-learn.
Установка и импорт библиотеки NumPy
Прежде чем начать использовать NumPy, необходимо установить библиотеку. Это можно сделать с помощью pip:
pip install numpy
После установки NumPy импортируйте библиотеку в свой Python скрипт:
import numpy as np
Создание двумерных массивов с помощью NumPy
Использование numpy.array() для создания массивов из списков
Самый простой способ создать двумерный массив в NumPy — использовать функцию numpy.array(), передав ей в качестве аргумента список списков. Каждый внутренний список будет представлять собой строку массива.
import numpy as np
from typing import List
def create_array_from_lists(data: List[List[int]]) -> np.ndarray:
"""Creates a NumPy array from a list of lists.
Args:
data: A list of lists representing the array data.
Returns:
A NumPy array.
"""
arr: np.ndarray = np.array(data)
return arr
data: List[List[int]] = [[1, 2, 3], [4, 5, 6]]
arr: np.ndarray = create_array_from_lists(data)
print(arr)
# Output:
# [[1 2 3]
# [4 5 6]]
Создание массивов заданной формы с помощью numpy.zeros() и numpy.ones()
Функции numpy.zeros() и numpy.ones() позволяют создать массивы, заполненные нулями и единицами соответственно. Первый аргумент определяет форму массива (количество строк и столбцов).
import numpy as np
def create_zeros_array(rows: int, cols: int) -> np.ndarray:
"""Creates a NumPy array filled with zeros.
Args:
rows: The number of rows in the array.
cols: The number of columns in the array.
Returns:
A NumPy array filled with zeros.
"""
arr: np.ndarray = np.zeros((rows, cols))
return arr
def create_ones_array(rows: int, cols: int) -> np.ndarray:
"""Creates a NumPy array filled with ones.
Args:
rows: The number of rows in the array.
cols: The number of columns in the array.
Returns:
A NumPy array filled with ones.
"""
arr: np.ndarray = np.ones((rows, cols))
return arr
zeros_array: np.ndarray = create_zeros_array(2, 3)
print(zeros_array)
# Output:
# [[0. 0. 0.]
# [0. 0. 0.]]
ones_array: np.ndarray = create_ones_array(3, 2)
print(ones_array)
# Output:
# [[1. 1.]
# [1. 1.]
# [1. 1.]]
Генерация массивов с последовательностью значений: numpy.arange() и numpy.linspace()
Функция numpy.arange() создает одномерный массив с последовательностью значений, аналогично встроенной функции range(). Для создания двумерного массива, можно использовать reshape(), чтобы изменить форму.
numpy.linspace() создает массив с равномерно распределенными значениями в заданном интервале. Также полезно использовать reshape() для получения двумерной структуры.
import numpy as np
def create_arange_array(start: int, stop: int, step: int, rows: int, cols: int) -> np.ndarray:
"""Creates a NumPy array with a sequence of values using arange and reshapes it.
Args:
start: The start value of the sequence.
stop: The end value of the sequence (exclusive).
step: The step size.
rows: The number of rows in the array.
cols: The number of columns in the array.
Returns:
A NumPy array with the reshaped sequence.
"""
arr: np.ndarray = np.arange(start, stop, step).reshape(rows, cols)
return arr
def create_linspace_array(start: float, stop: float, num: int, rows: int, cols: int) -> np.ndarray:
"""Creates a NumPy array with evenly spaced values using linspace and reshapes it.
Args:
start: The start value of the sequence.
stop: The end value of the sequence (inclusive).
num: The number of evenly spaced values to generate.
rows: The number of rows in the array.
cols: The number of columns in the array.
Returns:
A NumPy array with the reshaped sequence.
"""
arr: np.ndarray = np.linspace(start, stop, num).reshape(rows, cols)
return arr
arange_array: np.ndarray = create_arange_array(0, 6, 1, 2, 3)
print(arange_array)
# Output:
# [[0 1 2]
# [3 4 5]]
linspace_array: np.ndarray = create_linspace_array(0, 1, 6, 2, 3)
print(linspace_array)
# Output:
# [[0. 0.2 0.4]
# [0.6 0.8 1. ]]
Создание единичной матрицы с помощью numpy.eye()
Единичная матрица — это квадратная матрица, у которой все элементы на главной диагонали равны 1, а остальные элементы равны 0. Функция numpy.eye() позволяет создать единичную матрицу заданного размера.
import numpy as np
def create_identity_matrix(n: int) -> np.ndarray:
"""Creates a NumPy identity matrix.
Args:
n: The size of the identity matrix (number of rows and columns).
Returns:
A NumPy identity matrix.
"""
identity_matrix: np.ndarray = np.eye(n)
return identity_matrix
identity_matrix: np.ndarray = create_identity_matrix(3)
print(identity_matrix)
# Output:
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
Размеры и форма двумерных массивов
Определение размера массива: shape
Атрибут shape возвращает кортеж, содержащий размеры массива по каждой оси. Для двумерного массива shape вернет (количество строк, количество столбцов).
import numpy as np
def get_array_shape(arr: np.ndarray) -> tuple[int, ...]:
"""Returns the shape of a NumPy array.
Args:
arr: The NumPy array.
Returns:
A tuple representing the shape of the array.
"""
return arr.shape
arr: np.ndarray = np.array([[1, 2, 3], [4, 5, 6]])
shape: tuple[int, ...] = get_array_shape(arr)
print(shape) # Output: (2, 3)
Изменение формы массива: reshape()
Метод reshape() позволяет изменить форму массива, не изменяя его данные. Важно, чтобы общее количество элементов в массиве оставалось прежним.
import numpy as np
def reshape_array(arr: np.ndarray, rows: int, cols: int) -> np.ndarray:
"""Reshapes a NumPy array.
Args:
arr: The NumPy array.
rows: The new number of rows.
cols: The new number of columns.
Returns:
A NumPy array with the new shape.
Raises:
ValueError: If the new shape is incompatible with the original size.
"""
try:
reshaped_array: np.ndarray = arr.reshape(rows, cols)
return reshaped_array
except ValueError as e:
raise ValueError("Incompatible shape for reshaping.") from e
arr: np.ndarray = np.arange(6)
reshaped_arr: np.ndarray = reshape_array(arr, 2, 3)
print(reshaped_arr)
# Output:
# [[0 1 2]
# [3 4 5]]
Доступ к элементам и срезы двумерных массивов
Индексация элементов: доступ к конкретным значениям
Для доступа к элементам двумерного массива используется двойная индексация: array[номер_строки, номер_столбца]. Индексация начинается с 0.
import numpy as np
def access_element(arr: np.ndarray, row: int, col: int) -> int:
"""Accesses an element in a NumPy array using row and column indices.
Args:
arr: The NumPy array.
row: The row index.
col: The column index.
Returns:
The element at the specified row and column.
"""
return arr[row, col]
arr: np.ndarray = np.array([[1, 2, 3], [4, 5, 6]])
element: int = access_element(arr, 0, 1)
print(element) # Output: 2
Срезы: извлечение подмассивов
Срезы позволяют извлекать подмассивы из исходного массива. Синтаксис срезов: array[начало_строки:конец_строки, начало_столбца:конец_столбца]. Если начало или конец не указаны, подразумевается начало или конец массива соответственно.
import numpy as np
def get_subarray(arr: np.ndarray, row_start: int, row_end: int, col_start: int, col_end: int) -> np.ndarray:
"""Extracts a subarray from a NumPy array using slicing.
Args:
arr: The NumPy array.
row_start: The starting row index.
row_end: The ending row index (exclusive).
col_start: The starting column index.
col_end: The ending column index (exclusive).
Returns:
A NumPy subarray.
"""
subarray: np.ndarray = arr[row_start:row_end, col_start:col_end]
return subarray
arr: np.ndarray = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
subarray: np.ndarray = get_subarray(arr, 0, 2, 1, 3)
print(subarray)
# Output:
# [[2 3]
# [5 6]]
Булева индексация: фильтрация элементов по условию
Булева индексация позволяет выбирать элементы массива, соответствующие определенному условию. Создается булев массив той же формы, что и исходный, где True соответствует элементам, удовлетворяющим условию, а False — нет. Затем этот булев массив используется для индексации исходного массива.
import numpy as np
def filter_array(arr: np.ndarray, condition: np.ndarray) -> np.ndarray:
"""Filters a NumPy array based on a boolean condition.
Args:
arr: The NumPy array.
condition: A boolean array of the same shape as arr.
Returns:
A NumPy array containing elements where the condition is True.
"""
filtered_array: np.ndarray = arr[condition]
return filtered_array
arr: np.ndarray = np.array([[1, 2, 3], [4, 5, 6]])
condition: np.ndarray = arr > 3
print(condition)
# Output:
# [[False False False]
# [ True True True]]
filtered_arr: np.ndarray = filter_array(arr, condition)
print(filtered_arr)
# Output:
# [4 5 6]
Примеры и практическое применение
Пример 1: Создание матрицы с заданными значениями
Представим, что нам нужно создать матрицу, представляющую посещаемость сайта по дням недели и часам дня. Строки соответствуют дням недели (понедельник — 0, вторник — 1 и т.д.), а столбцы – часам дня (0-23). Значения в матрице – количество посещений.
import numpy as np
def create_traffic_matrix(traffic_data: List[List[int]]) -> np.ndarray:
"""Creates a traffic matrix from a list of lists.
Args:
traffic_data: A list of lists representing the traffic data.
Returns:
A NumPy array representing the traffic matrix.
"""
traffic_matrix: np.ndarray = np.array(traffic_data)
return traffic_matrix
traffic_data: List[List[int]] = [
[100, 120, 150, 130, 110, 90, 80, 70, 60, 50, 40, 30, 20, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110],
[110, 130, 160, 140, 120, 100, 90, 80, 70, 60, 50, 40, 30, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
[120, 140, 170, 150, 130, 110, 100, 90, 80, 70, 60, 50, 40, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130],
[130, 150, 180, 160, 140, 120, 110, 100, 90, 80, 70, 60, 50, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140],
[140, 160, 190, 170, 150, 130, 120, 110, 100, 90, 80, 70, 60, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150],
[150, 170, 200, 180, 160, 140, 130, 120, 110, 100, 90, 80, 70, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160],
[160, 180, 210, 190, 170, 150, 140, 130, 120, 110, 100, 90, 80, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170],
]
traffic_matrix: np.ndarray = create_traffic_matrix(traffic_data)
print(traffic_matrix)
Пример 2: Преобразование данных из файла в двумерный массив
Часто данные для анализа хранятся в файлах (например, CSV). NumPy позволяет легко загрузить данные из файла в двумерный массив.
import numpy as np
def load_data_from_file(filename: str, delimiter: str = ",") -> np.ndarray:
"""Loads data from a file into a NumPy array.
Args:
filename: The name of the file.
delimiter: The delimiter used in the file (default: ",").
Returns:
A NumPy array containing the data from the file.
Raises:
FileNotFoundError: If the file does not exist.
ValueError: If there is an issue loading the data.
"""
try:
data: np.ndarray = np.loadtxt(filename, delimiter=delimiter)
return data
except FileNotFoundError:
raise FileNotFoundError(f"File not found: {filename}")
except ValueError as e:
raise ValueError(f"Error loading data from file: {e}")
# Create a dummy CSV file for demonstration
with open("data.csv", "w") as f:
f.write("1,2,3\n")
f.write("4,5,6\n")
# Load the data from the CSV file
data: np.ndarray = load_data_from_file("data.csv")
print(data)
# Output:
# [[1. 2. 3.]
# [4. 5. 6.]]
Пример 3: Выполнение математических операций с матрицами
NumPy предоставляет широкий набор функций для выполнения математических операций с матрицами, таких как сложение, вычитание, умножение и транспонирование.
import numpy as np
def perform_matrix_operations(matrix1: np.ndarray, matrix2: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Performs matrix addition, subtraction, and multiplication.
Args:
matrix1: The first NumPy array.
matrix2: The second NumPy array.
Returns:
A tuple containing the addition, subtraction, and element-wise multiplication results.
Raises:
ValueError: If the matrices have incompatible shapes for addition or subtraction.
"""
try:
addition_result: np.ndarray = matrix1 + matrix2
subtraction_result: np.ndarray = matrix1 - matrix2
except ValueError as e:
raise ValueError("Matrices must have the same shape for addition and subtraction.") from e
multiplication_result: np.ndarray = matrix1 * matrix2 # Element-wise multiplication
return addition_result, subtraction_result, multiplication_result
matrix1: np.ndarray = np.array([[1, 2], [3, 4]])
matrix2: np.ndarray = np.array([[5, 6], [7, 8]])
addition_result, subtraction_result, multiplication_result = perform_matrix_operations(matrix1, matrix2)
print("Addition:\n", addition_result)
# Output:
# [[ 6 8]
# [10 12]]
print("Subtraction:\n", subtraction_result)
# Output:
# [[-4 -4]
# [-4 -4]]
print("Element-wise Multiplication:\n", multiplication_result)
# Output:
# [[ 5 12]
# [21 32]]