Appearance
7. Универсальное индексирование и выборка подмассивов фичей
Разделение датасета на признаки X и таргет y
Изоляция матрицы признаков (Features) и целевой переменной (Target)
В машинном обучении и инженерии искусственного интеллекта данные табличных датасетов практически всегда делятся на две независимые структуры:
- Матрица признаков
X(Features): Многомерный массив (двумерная таблица), содержащий все входные параметры, по которым модель будет учиться. - Вектор ответов
y(Target): Одномерный массив, содержащий правильные метки классов или целевые числовые значения.
Для быстрого разделения таблиц на X и y без создания громоздких циклов используется комбинация оператора .loc[:, :] и встроенного метода dataframe.drop(labels, axis). Метод .drop() удаляет указанные столбцы или строки из структуры. Чтобы удалить именно столбец признака (колонку), необходимо строго передать параметр axis=1 (горизонтальная ось столбцов). По умолчанию .drop() возвращает новый объект, не изменяя исходную таблицу в памяти.
python
import pandas
raw_dataset = {
"feature_length": [1.4, 4.9, 1.5],
"feature_width": [0.2, 1.4, 0.2],
"target_species": [0, 1, 0]
}
df = pandas.DataFrame(raw_dataset)
# Extracting the feature matrix X by dropping the target column along axis=1
X = df.drop("target_species", axis=1)
# Extracting the target vector y directly by column name slice
y = df["target_species"]
print("Feature Matrix X shape:", X.shape) # Outputs: (3, 2)
print("Target Vector y shape:", y.shape) # Outputs: (3,)Выборка столбцов: ключ, список и атрибут
Обращение к таблице по одиночному строковому ключу возвращает одномерную Series (колонку). Для передачи данных в ML-пайплайн часто нужен не один столбец, а сразу несколько: тогда в скобки передается список имён колонок, и на выходе снова получается двумерный pandas.DataFrame. Классическая ловушка — «одна колонка в списке»: результат по-прежнему остается DataFrame (с формой (N, 1)), а не Series, что ломает ряд конструкторов моделей. Наконец, если имя столбца является корректным идентификатором Python, доступ к нему возможен и через атрибут объекта.
python
import pandas
raw_dataset = {
"feature_length": [1.4, 4.9, 1.5],
"feature_width": [0.2, 1.4, 0.2],
"target_species": [0, 1, 0]
}
df = pandas.DataFrame(raw_dataset)
# Single key lookup returns a one-dimensional Series
single_column = df["feature_length"]
print("Single column type:", type(single_column)) # Outputs: <class 'pandas.core.series.Series'>
# A list of keys returns a two-dimensional DataFrame subset
subset_table = df[["feature_length", "feature_width"]]
print("Two-column subset type:", type(subset_table)) # Outputs: <class 'pandas.core.frame.DataFrame'>
# Classic trap: a single key wrapped in a list STILL returns a DataFrame (N, 1), not a Series
one_column_in_list = df[["feature_length"]]
print("List-wrapped single column type:", type(one_column_in_list)) # Outputs: <class 'pandas.core.frame.DataFrame'>
# Attribute-style access is equivalent to the key lookup (valid identifiers only)
attribute_column = df.feature_width
print("Attribute access equals key lookup:", attribute_column.equals(df["feature_width"])) # Outputs: TrueПрямой срез строк и скрытые ошибки
С квадратными скобками по позициям можно работать «как со списком», но только для срезов строк: df[1:4] вырежет строки с первой по третью. Запрос отдельного элемента скалярным числом (df[1]) не интерпретируется как выборка строки — Pandas ищет колонку с именем 1 и бросает KeyError. Поэтому для поэлементной адресации строк всегда применяются операторы .loc[]/.iloc[] из Урока 6.
python
import pandas
# Table with explicit integer row indices 1..4
metrics_table = pandas.DataFrame(
{"feature_A": [10.0, 20.0, 30.0, 40.0], "feature_B": [1, 2, 3, 4]},
index=[1, 2, 3, 4]
)
# Integer slices are applied to the ROW axis and work like in Python lists
print(metrics_table[:1])
# Outputs only the first row (index 1)
print(metrics_table[1:4])
# Positional slice: rows at positions 1-3, i.e. rows with indices 2, 3 and 4 (the row with index 1 is excluded)
# Scalar row selection is NOT supported: Pandas looks for a column named 1
# and raises KeyError: 1. Use .loc / .iloc (Lesson 6) instead.
# metrics_table[1] # Raises: KeyError: 1Добавление новых расчетных колонок
В процессе проектирования признаков (Feature Engineering) часто требуется создать новые столбцы на основе уже существующих (например, перемножить два признака или вычислить их логарифм). В Pandas добавление новой колонки реализуется простым присваиванием по новому имени ключа, как в стандартных словарях Python.
python
import pandas
df_area = pandas.DataFrame({"length": [3, 5], "width": [2, 4]})
# Creating a new feature column automatically via vectorized operations
df_area["calculated_area"] = df_area["length"] * df_area["width"]Условная модификация данных
Быстрая замена значений через метод .where()
Если внутри определенного столбца признаков необходимо точечно заменить элементы по логическому условию (например, обрезать слишком высокие значения или заменить аномалии), в Pandas применяется встроенный векторизованный метод series.where(condition, other).
Механизм его работы имеет важную синтаксическую особенность: он оставляет без изменений те элементы, для которых логическое условие condition вернуло True. Если же условие вернуло False, элемент заменяется на значение, переданное в параметр other. Этот метод работает на C-скорости без выделения лишней оперативной памяти.
python
import pandas
scores = pandas.Series([0.15, 0.92, -0.45, 0.88])
# If condition is True (value >= 0) -> keep it, else -> replace with 0.0
# This effectively replicates the neural network ReLU activation trigger
activated_scores = scores.where(scores >= 0, 0.0)
print(activated_scores) # Outputs: [0.15, 0.92, 0.00, 0.88]Упражнения базовые (5 шт) (только с опорой на объясненную в данном уроке теорию)
1. Изоляция матрицы признаков X через удаление столбца
Задача: Дан DataFrame df_run = pandas.DataFrame({"feature_1": [1.5, 2.5], "feature_2": [5.5, 6.5], "label": [1, 0]}). С помощью метода .drop() удалите столбец "label", указав правильное направление оси axis, чтобы получить чистую матрицу признаков X. Выведите форму .shape полученного объекта.
Посмотреть решение
python
import pandas
df_run = pandas.DataFrame({"feature_1": [1.5, 2.5], "feature_2": [5.5, 6.5], "label": [1, 0]})
# Dropping the target variable column vertically along the horizontal features axis
X = df_run.drop("label", axis=1)
print("Features matrix dimensions layout:", X.shape) # Outputs: (2, 2)2. Динамическое добавление расчетного признака
Задача: Создайте таблицу df_weights = pandas.DataFrame({"layer_weights": [0.5, -1.2, 2.0]}). Добавьте в нее новую колонку с именем "squared_weights", значения которой должны быть равны элементам первого столбца, возведенным в квадрат векторизованной операцией. Выведите итоговую таблицу.
Посмотреть решение
python
import pandas
df_weights = pandas.DataFrame({"layer_weights": [0.5, -1.2, 2.0]})
# Appending a calculated feature track column directly
df_weights["squared_weights"] = df_weights["layer_weights"] ** 2
print(df_weights)3. Точечная замена отрицательных сигналов через .where()
Задача: Дан одномерный объект signals = pandas.Series([-5, 12, -1, 15, 0]). Используя метод .where(), замените все отрицательные значения (строго меньше 0) на дефолтную константу -999. Выведите измененную структуру.
Посмотреть решение
python
import pandas
signals = pandas.Series([-5, 12, -1, 15, 0])
# Condition checks where to KEEP the values (values >= 0 are kept, others replaced)
sanitized_signals = signals.where(signals >= 0, -999)
print(sanitized_signals) # Outputs: [-999, 12, -999, 15, 0]4. Извлечение изолированного столбца таргета
Задача: Из таблицы df_run = pandas.DataFrame({"feature_1":, "feature_2": [5.5, 6.5], "label": [1, 0]}) выделите столбец "label" напрямую по имени ключа. Проверьте тип полученного объекта и убедитесь, что он представляет собой одномерную структуру pandas.Series.
Посмотреть решение
python
import pandas
df_run = pandas.DataFrame({"feature_1": [1.5, 2.5], "feature_2": [5.5, 6.5], "label": [1, 0]})
# Extracting target label vector
y_target = df_run["label"]
print("Object classification type:", type(y_target)) # <class 'pandas.core.series.Series'>5. Удаление строк датасета по индексу
Задача: Метод .drop() умеет удалять не только столбцы, но и строки, если передать числовой индекс строки и параметр axis=0. Дан DataFrame df_samples = pandas.DataFrame({"A": [1, 2, 3]}, index=["s1", "s2", "s3"]). Удалите из него строку с меткой "s2". Выведите результат.
Посмотреть решение
python
import pandas
df_samples = pandas.DataFrame({"A": [1, 2, 3]}, index=["s1", "s2", "s3"])
# Dropping a single row using its explicit label index identifier along axis=0
reduced_df = df_samples.drop(labels=["s2"], axis=0)
print(reduced_df)Упражнения смешанные (5 шт) (включают материал прошлых уроков)
6. Удаление признаков и аудит метаданных памяти полученной матрицы X
Задача: Создайте таблицу логов обучения raw_dataset = pandas.DataFrame({"feature_loss": [0.85, 0.42, 0.12], "feature_accuracy": [0.60, 0.78, 0.95], "epoch_id": [1, 2, 3]}) (Урок 5). Выделите из нее чистую матрицу признаков X, удалив столбец "epoch_id" по горизонтальной оси axis=1 (Урок 7). Для полученного объекта X посчитайте точный физический объем используемой оперативной памяти в байтах методом .memory_usage(deep=True) (Урок 5).
Посмотреть решение
python
import pandas
raw_dataset = pandas.DataFrame({"feature_loss": [0.85, 0.42, 0.12], "feature_accuracy": [0.60, 0.78, 0.95], "epoch_id": [1, 2, 3]})
# Step 1: Isolate the feature matrix chunk using column drop mechanics (Lesson 7)
X_features = raw_dataset.drop("epoch_id", axis=1)
# Step 2: Running прецизионный memory metrics audit (Lesson 5)
bytes_footprint = X_features.memory_usage(deep=True)
print("Bytes consumed per remaining features columns:\n", bytes_footprint)7. Булево маскирование с последующей условной заменой аномалий .where()
Задача: Дан DataFrame сырых сигналов df_signals = pandas.DataFrame({"amplitude": [1.5, -99.0, 4.2, -99.0, 3.8], "channel": [0, 1, 0, 1, 0]}) (Урок 5). С помощью оператора .loc[] извлеките подматрицу строк, относящихся только к нулевому каналу "channel" == 0 (Урок 6). К полученному столбцу "amplitude" отфильтрованных строк примените метод условной замены .where(), заместив любые значения, которые строго меньше 0.0, на нейтральную константу 0.0 (Урок 7). Выведите очищенный срез.
Посмотреть решение
python
import pandas
df_signals = pandas.DataFrame({"amplitude": [1.5, -99.0, 4.2, -99.0, 3.8], "channel": [0, 1, 0, 1, 0]})
# Step 1: Filter rows targeting specific metadata channels (Lesson 6)
channel_zero_df = df_signals.loc[df_signals["channel"] == 0, :].copy()
# Step 2: Running vectorized conditional value imputation replacement (Lesson 7)
# Keep values if condition amplitude >= 0 is True, else replace with 0.0
channel_zero_df["amplitude"] = channel_zero_df["amplitude"].where(channel_zero_df["amplitude"] >= 0, 0.0)
print(channel_zero_df)8. Добавление расчетного столбца логарифма на базе ufuncs из NumPy
Задача: Инициализируйте таблицу вероятностей предсказаний классификатора df_predictions = pandas.DataFrame({"confidence": [0.99, 0.85, 0.45, 0.12]}) (Урок 5). Используя ufunc-функцию вычисления натурального логарифма numpy.log() из модуля NumPy (Урок 8 модуля NumPy), рассчитайте вектор логарифмических штрафов на основе столбца "confidence". Запишите полученный вектор в новый расчетный столбец таблицы с именем "log_penalty" напрямую через оператор присваивания ключа (Урок 7). Выведите таблицу.
Посмотреть решение
python
import numpy
import pandas
df_predictions = pandas.DataFrame({"confidence": [0.99, 0.85, 0.45, 0.12]})
# Combining numpy universal mathematical functions with pandas assignments (NumPy Lesson 8 & Pandas Lesson 7)
df_predictions["log_penalty"] = -numpy.log(df_predictions["confidence"])
print(df_predictions)9. Сортировка по индексам перед разделением на X и y
Задача: Дана неотсортированная таблица логов экспериментов ИИ: df_experiments = pandas.DataFrame({"metric": [0.92, 0.44], "target": [1, 0]}, index=["run_2", "run_1"]) (Урок 5). Выполните алфавитную сортировку строк по индексным меткам на месте (Урок 4). После упорядочивания примените метод .drop(axis=1) для выделения матрицы признаков X без столбца "target", а вектор y заберите напрямую по ключу (Урок 7). Выведите X и y.
Посмотреть решение
python
import pandas
df_experiments = pandas.DataFrame({"metric": [0.92, 0.44], "target": [1, 0]}, index=["run_2", "run_1"])
# Step 1: Sorting chronological structures in-place via indices (Lesson 4)
df_experiments.sort_index(inplace=True)
# Step 2: Separate features variables matrix and targets response vectors (Lesson 7)
X_features = df_experiments.drop("target", axis=1)
y_target = df_experiments["target"]
print("Sorted Matrix X:\n", X_features)
print("Sorted Vector y:\n", y_target)10. Условная модификация унаследованного низкоуровневого буфера через numpy.where()
Задача: Создайте одномерный объект series_data = pandas.Series([1.5, -2.5, 3.0, -1.0]) (Урок 2). Напишите векторизованную условную замену элементов с использованием низкоуровневой функции numpy.where(condition, x, y) из модуля NumPy (Урок 10 модуля NumPy): если элемент строго больше 0.0, оставьте его без изменений, иначе замените на 0.0. Перезапишите результат обратно в буфер значений объекта series_data. Выведите итоговую структуру и посмотрите в комментарии, почему в Pandas встроенный метод .where() работает инвертировано по отношению к numpy.where().
Посмотреть решение
python
import numpy
import pandas
series_data = pandas.Series([1.5, -2.5, 3.0, -1.0])
# Using low-level numpy.where which replaces elements when condition is FALSE (NumPy Lesson 10)
# Syntax: numpy.where(condition, if_true, if_false)
# Pandas series.where() keeps values if TRUE, replaces if FALSE (Lesson 7)
series_data[:] = numpy.where(series_data > 0, series_data, 0.0)
print("Sanitized activated series elements:\n", series_data)