Как найти противоречия в данных Pandas
Я знаю, как удалить дубликаты строк из исходных данных в Pandas: drop_duplicates
Но при подготовке данных перед обучение НС может быть так, что в двух или более строках признаки совпадают, а предсказываемые значения отличаются. Например: (x1 x2 x3) -> 1 и (x1 x2 x3) -> 0. Как обнаружить такие ситуации ?
И сразу встает вопрос, как их обработать? Например, одну из строк выбросить - оставить только с 1. Как?
Или, взять среднее, т.е. такие строки убрать, а вместо них вставить одну со средним значением предсказываемого значения: (x1 x2 x3) -> 1/2
Ответы (1 шт):
Вопрос
Пусть есть такие данные, с повторениями в объектах:
import pandas as pd
data = pd.DataFrame({
"feature1": [1, 1, 3],
"feature2": [10, 10, 30],
"target": [-1, -2, -3],
})
data.to_markdown()
| | feature1 | feature2 | target |
|---:|-----------:|-----------:|---------:|
| 0 | 1 | 10 | -1 |
| 1 | 1 | 10 | -2 |
| 2 | 3 | 30 | -3 |
- Как выбросить повторения, оставив только одну строку для каждого повторения?
| feature1 | feature2 | target |
|-----------:|-----------:|---------:|
| 1 | 10 | -1 |
| 3 | 30 | -3 |
- Как схлопнуть повторения, взяв среднее для каждой группы?
| feature1 | feature2 | target |
|-----------:|-----------:|---------:|
| 1 | 10 | -1.5 |
| 3 | 30 | -3 |
- Каким образом обычно разрешают такие ситуации с данными при подготовке к обучению нейросети?
Ответ
Не имею достаточного опыта с нейросетями, но могу предложить возможные алгоритмы для выполнения первых двух пунктов.
- Однострочное решение:
dropped_data = data.iloc[data.drop(columns="target").drop_duplicates().index]
dropped_data.to_markdown()
| | feature1 | feature2 | target |
|---:|-----------:|-----------:|---------:|
| 0 | 1 | 10 | -1 |
| 2 | 3 | 30 | -3 |
Как это работает? Убираем колонку target из исходных данных (.drop(columns="target")), получаем таблицу
| | feature1 | feature2 |
|---:|-----------:|-----------:|
| 0 | 1 | 10 |
| 1 | 1 | 10 |
| 2 | 3 | 30 |
Далее удаляем дубликаты (.drop_duplicates()), получаем таблицу
| | feature1 | feature2 |
|---:|-----------:|-----------:|
| 0 | 1 | 10 |
| 2 | 3 | 30 |
Забираем индексы (.index): [0, 2].
Используем .iloc для получения строчек начального датафрейма по индексам.
- Однострочное решение:
mean_data = data.groupby(list(set(data.columns) - { "target" })).mean().reset_index()
mean_data.to_markdown()
| | feature2 | feature1 | target |
|---:|-----------:|-----------:|---------:|
| 0 | 10 | 1 | -1.5 |
| 1 | 30 | 3 | -3 |
Как это работает? Выбираем колонки с признаками (set(data.columns) - { "target" }), группируем по ним (groupby принимает список, поэтому предварительно преобразуем в list), берем среднее от оставшихся колонок, получаем таблицу:
| | target |
|:--------|---------:|
| (10, 1) | -1.5 |
| (30, 3) | -3 |
После этого сбрасываем индекс (.reset_index()), чтобы вернуть значения из индекса в столбцы.