Appearance
9. Предобработка AI-данных: обработка пропусков (NaN/None) и дубликатов
Стратегии импутации (заполнения) пропусков в ML
Поиск и аудит скрытых пустот в датасете
В реальной практике ИИ-инженера сырые датасеты часто содержат пропуски. Они возникают из-за сбоев в работе датчиков, ошибок логирования или неполных анкет пользователей. Наличие пропущенных значений (маркеров NaN или объектов None) блокирует математические операции и вызывает критические ошибки при попытке передать данные в нейронную сеть.
Первым шагом предобработки всегда является локализация и аудит пустот. Для этого к DataFrame применяется векторизованный метод .isna(), который заменяет каждое значение в таблице на булев флаг (True, если значение пропущено). Чтобы быстро оценить масштаб проблемы в разрезе признаков, к полученной маске добавляют вертикальный агрегатор .sum() (по умолчанию axis=0), сжимающий строки.
python
import pandas
raw_corrupted_data = {
"feature_age": [23, 45, pandas.NA, 31],
"feature_score": [0.85, pandas.NA, 0.12, 0.99]
}
df_corrupted = pandas.DataFrame(raw_corrupted_data)
# Counting the absolute number of missing fields for each feature column
print(df_corrupted.isna().sum())
# Outputs:
# feature_age 1
# feature_score 1
# dtype: int64Математические стратегии борьбы с пропусками
Когда пропуски обнаружены, ИИ-инженер выбирает одну из двух фундаментальных стратегий предобработки данных:
- Жесткое удаление (
dataframe.dropna()): Полностью выбрасывает строки или столбцы, содержащие хотя бы одно пропущенное значение. Стратегия применима, если пропусков очень мало (менее 1–5% от всей выборки), чтобы не потерять важную информацию для обучения. Параметрaxis=0удаляет строки, аaxis=1— столбцы. - Заполнение или Импутация (
dataframe.fillna()): Заменяет маркеры пропусков на фиксированные числовые значения. В машинном обучении хорошим тоном считается заполнять пустоты средним арифметическим значением (.mean()) или медианой (.median()) данного столбца признаков, рассчитанной по остальным валидным объектам.
python
import pandas
df_weights = pandas.DataFrame({"weight": [1.5, pandas.NA, 2.5, 4.0]})
# Strategy 1: Drop rows containing any missing value tokens
clean_rows = df_weights.dropna(axis=0)
# Strategy 2: Impute missing entries with the feature's calculated mean scalar
column_mean = df_weights["weight"].mean()
df_weights["weight"] = df_weights["weight"].fillna(column_mean)Очистка от дубликатов
Обнаружение и удаление идентичных строк
Дубликаты объектов (абсолютно одинаковые строки в таблице) искусственно завышают важность отдельных паттернов данных, смещают баланс классов и могут привести к переобучению (overfitting) модели, если один и тот же объект попадет и в обучающую, и в тестовую выборки.
Для очистки множества от повторений Pandas предоставляет два эффективных C-метода:
dataframe.duplicated()— возвращает булеву маску, где строки, повторяющие ранее встреченные записи, помечаются какTrue.dataframe.drop_duplicates()— находит, удаляет все дублирующиеся строки и возвращает чистый оттянутый датасет.
Оба метода поддерживают управляющий параметр inplace=True для проведения модификации физического буфера памяти на месте без лишних аллокаций RAM.
python
import pandas
raw_logs = {"feature_X": [1, 1, 2, 2], "feature_Y": [5, 5, 6, 6]}
df_logs = pandas.DataFrame(raw_logs)
# Removing duplicated row instances directly in-place
df_logs.drop_duplicates(inplace=True)
print(df_logs.shape) # Outputs reduced geometry: (2, 2)Упражнения базовые (5 шт) (только с опорой на объясненную в данном уроке теорию)
1. Подсчет пропущенных полей в таблице
Задача: Дан DataFrame df_metrics = pandas.DataFrame({"loss": [0.1, pandas.NA, 0.4], "acc": [pandas.NA, 0.8, 0.9]}). Напишите строку кода, которая подсчитывает общее количество пропущенных значений для каждого столбца. Выведите результат.
Посмотреть решение
python
import pandas
df_metrics = pandas.DataFrame({"loss": [0.1, pandas.NA, 0.4], "acc": [pandas.NA, 0.8, 0.9]})
# Combining missing detectors and sum aggregators vertically
missing_counts = df_metrics.isna().sum()
print(missing_counts)2. Жесткое удаление поврежденных строк
Задача: На основе объекта df_metrics из предыдущего упражнения примените метод .dropna(), чтобы удалить все строки, содержащие хотя бы один маркер пропуска. Выведите очищенный DataFrame.
Посмотреть решение
python
import pandas
df_metrics = pandas.DataFrame({"loss": [0.1, pandas.NA, 0.4], "acc": [pandas.NA, 0.8, 0.9]})
# Deleting rows along the samples index axis axis=0
sanitized_df = df_metrics.dropna(axis=0)
print(sanitized_df) # Contains only the last row index 23. Импутация пропусков константой на месте
Задача: Создайте одномерную структуру biases = pandas.Series([0.15, pandas.NA, -0.44]). Используя метод .fillna(), замените пропущенное значение на фиксированную константу 0.0 принудительно на месте (inplace=True). Выведите измененную структуру.
Посмотреть решение
python
import pandas
biases = pandas.Series([0.15, pandas.NA, -0.44])
# Imputing static scalar value to patch missing fields inside memory
biases.fillna(0.0, inplace=True)
print(biases)4. Поиск дублирующихся строк объектов
Задача: Дан DataFrame df_samples = pandas.DataFrame({"X": [1, 1, 2, 1], "Y": [10, 10, 12, 10]}). Примените метод .duplicated(), чтобы получить булеву маску дубликатов, и выведите её на экран.
Посмотреть решение
python
import pandas
df_samples = pandas.DataFrame({"X": [1, 1, 2, 1], "Y": [10, 10, 12, 10]})
# Screening for identical sample duplicates records
duplicates_mask = df_samples.duplicated()
print(duplicates_mask) # Rows at indices 1 and 3 will be marked True5. Очистка датасета от повторений
Задача: На основе объекта df_samples из прошлого упражнения вызовите метод .drop_duplicates(), чтобы получить очищенную таблицу, где каждая строка уникальна. Выведите её форму .shape.
Посмотреть решение
python
import pandas
df_samples = pandas.DataFrame({"X": [1, 1, 2, 1], "Y": [10, 10, 12, 10]})
# Dropping duplicate rows from the dataset block
clean_df = df_samples.drop_duplicates()
print("Sanitized unique shape geometry:", clean_df.shape) # Outputs: (2, 2)Упражнения смешанные (5 шт) (включают материал прошлых уроков)
6. Загрузка CSV-файла с ограничением колонок и заполнением пропусков медианой
Задача: Прочитайте файл "raw_features.csv", ограничив загрузку только признаком ["feature_velocity"] с помощью параметра usecols (Урок 8). Извлеките этот столбец в виде объекта Series (Урок 2). Рассчитайте медиану по валидным элементам столбца с помощью метода .median() (Урок 5). Заполните все скрытые пропуски NaN этой вычисленной медианой на месте (Урок 9). Выведите очищенный вектор.
Посмотреть решение
python
import pandas
# Step 1: Read specific column array directly from storage (Lesson 8)
raw_df = pandas.read_csv(filepath_or_buffer="raw_features.csv", usecols=["feature_velocity"])
velocity_series = raw_df["feature_velocity"]
# Step 2: Compute median statistics metric (Lesson 5)
calculated_median = velocity_series.median()
# Step 3: Impute missing entries in place using the median (Lesson 9)
velocity_series.fillna(calculated_median, inplace=True)
print(velocity_series)7. Удаление дубликатов и выделение матрицы X из Parquet-файла
Задача: Загрузите бинарный колоночный файл данных "raw_batch.parquet" (Урок 8). Выполните операцию удаления полностью идентичных строк-дубликатов объектов на месте через .drop_duplicates(inplace=True) (Урок 9). После очистки примените метод .drop(axis=1), чтобы отделить чистую матрицу признаков X, убрав столбец разметки с именем "target_class" (Урок 7). Выведите форму .shape полученной матрицы X (Урок 5).
Посмотреть решение
python
import pandas
# Step 1: Highly optimized parquet file reading (Lesson 8)
raw_data_df = pandas.read_parquet(path="raw_batch.parquet")
# Step 2: Remove duplicated records inside memory buffer (Lesson 9)
raw_data_df.drop_duplicates(inplace=True)
# Step 3: Feature spaces isolation along axis=1 (Lesson 5 & Lesson 7)
matrix_X = raw_data_df.drop("target_class", axis=1)
print("Unique training samples feature space geometry shape:", matrix_X.shape)8. Сложное булево фильтрование строк датасета после жесткого удаления NaN
Задача: Дан DataFrame логов экспериментов df_experiments = pandas.DataFrame({"loss_rate": [0.85, pandas.NA, 0.02, 0.15], "status": ["active", "valid", "corrupted", "active"]}) (Урок 5). Жестко удалите строки, содержащие пропуски в данных, с помощью метода .dropna(axis=0) (Урок 9). К полученной чистой таблице примените оператор .loc[] для отбора строк, у которых показатель "loss_rate" строго меньше 0.5 и одновременно статус равен строго "active" (Урок 6). Выведите батч строк.
Посмотреть решение
python
import pandas
df_experiments = pandas.DataFrame({"loss_rate": [0.85, pandas.NA, 0.02, 0.15], "status": ["active", "valid", "corrupted", "active"]})
# Step 1: Discard any corrupted rows blocks from memory layout (Lesson 9)
sanitized_base_df = df_experiments.dropna(axis=0)
# Step 2: Extract subset rows complying with dual constraint criteria masks (Lesson 6)
target_batch_df = sanitized_base_df.loc[
(sanitized_base_df["loss_rate"] < 0.5) & (sanitized_base_df["status"] == "active"), :
]
print(target_batch_df)9. Сортировка по значениям Series после точечной импутации средним
Задача: Создайте одномерную структуру оценок точности scores = pandas.Series([0.78, pandas.NA, 0.92, 0.85, pandas.NA]) (Урок 2). Вычислите среднее арифметическое значение фичи методом .mean() (Урок 5). Заполните все маркеры пропусков этим средним значением (Урок 9). После импутации отсортируйте полученный плотный вектор по значениям элементов в порядке убывания через метод .sort_values(ascending=False) (Урок 4). Выведите результат.
Посмотреть решение
python
import pandas
scores = pandas.Series([0.78, pandas.NA, 0.92, 0.85, pandas.NA])
# Step 1: Calculate arithmetic feature average scalar (Lesson 5)
feature_mean = scores.mean()
# Step 2: Missing tokens imputation replacement (Lesson 9)
scores.fillna(feature_mean, inplace=True)
# Step 3: Descending sorting operation (Lesson 4)
ordered_scores = scores.sort_values(ascending=False)
print(ordered_scores)10. Векторизованный расчет экспоненциального сглаживания над очищенным C-буфером через NumPy
Задача: Дан DataFrame сырых логитов df_logits = pandas.DataFrame({"logits": [1.2, pandas.NA, -0.5, 1.2], "idx": [1, 2, 3, 1]}) (Урок 5). Удалите полностью все строки-дубликаты на месте (Урок 9). После удаления дубликатов заполните оставшиеся пропуски методом .fillna(0.0) и приведите столбец к строгому типу float64 через .astype("float64") (колонка, содержащая pandas.NA, по умолчанию имеет тип object, который векторизованные ufunc-функции NumPy не принимают) (Урок 9). Обратитесь к низкоуровневому C-буферу .values (Урок 2) и пропустите его сквозь векторизованную ufunc-функцию экспоненты numpy.exp() из модуля NumPy (Урок 8 модуля NumPy). Выведите результат.
Посмотреть решение
python
import numpy
import pandas
df_logits = pandas.DataFrame({"logits": [1.2, pandas.NA, -0.5, 1.2], "idx": [1, 2, 3, 1]})
# Step 1: Remove twin rows duplicates from container (Lesson 9)
df_logits.drop_duplicates(inplace=True)
# Step 2: Impute the missing field and cast the object buffer to strict float64
# (a column holding pandas.NA is inferred as object dtype, which NumPy ufuncs reject)
df_logits["logits"] = df_logits["logits"].fillna(0.0).astype("float64")
# Step 3: Stream clean C-array memory layout into a NumPy universal math_oge function (NumPy Lesson 8 & Pandas Lesson 2)
vectorized_exponentials = numpy.exp(df_logits["logits"].values)
print(vectorized_exponentials)