Вопрос или проблема
Недавно я сдавал практический экзамен на получение квалификации Data Scientist Associate в DataCamp. Всего было 5 заданий, и я смог выполнить все, кроме одного. В этом задании требовалось очистить DataFrame для продаж домов. Проблема в том, что, как мне кажется, описания некоторых требований к столбцам были недостаточными. Поэтому я пытаюсь понять, действительно ли я сделал что-то неправильно или это связано с тем, как представляется проект.
Ниже приведено полное описание выполнения Задачи 2 и код, который я написал для очистки DataFrame.
Перед тем как создать любые модели, нужно убедиться, что данные очищены.
Таблица ниже показывает, как должны выглядеть данные.
Создайте очищенную версию DataFrame.
-
Начать следует с данных в файле “house_sales.csv”.
-
Ваши результаты должны быть DataFrame под названием
clean_data
. -
Все названия столбцов и значения должны соответствовать таблице ниже.
Название столбца | Критерий |
---|---|
house_id | Номинальный. Уникальный идентификатор домов. Отсутствующие значения невозможны. |
city | Номинальный. Город, в котором находится дом. Один из ‘Silvertown’, ‘Riverford’, ‘Teasdale’ и ‘Poppleton’. Заменить отсутствующие значения на “Unknown”. |
sale_price | Дискретный. Цена продажи дома в целых долларах. Значения могут быть положительными числами, равными или большими нуля. Удалите отсутствующие записи. |
sale_date | Дискретный. Дата последней продажи дома. Замените отсутствующие значения на 2023-01-01. |
months_listed | Непрерывный. Количество месяцев, в течение которых дом был выставлен на рынке до его последней продажи, округленное до одного десятичного знака. Замените отсутствующие значения на среднее значение количества месяцев, округленное до одного десятичного знака. |
bedrooms | Дискретный. Количество спальных комнат в доме. Любые положительные значения, равные или большие нуля. Замените отсутствующие значения на среднее количество спальных комнат, округленное до ближайшего целого. |
house_type | Порядковый. Один из “Terraced”, “Semi-detached” или “Detached”. Замените отсутствующие значения самым распространенным типом дома. |
area | Непрерывный. Площадь дома в квадратных метрах, округленная до одного десятичного знака. Замените отсутствующие значения на среднее значение, округленное до одного десятичного знака. |
# Импорт необходимых пакетов и данных
import datetime as dt
house = pd.read_csv("house_sales.csv")
clean_data = pd.DataFrame()
# Преобразование house_id в номинальную категорию
house["house_id"] = house["house_id"].astype("category")
# Замена отсутствующих значений в city на Unknown
house["city"] = house["city"].str.replace("--", "Unknown")
# Преобразование city в категориальный тип
house["city"] = house["city"].astype("category")
# sale_price в формате int64 и не имеет отсутствующих значений
# Преобразуем sale_date в дискретные переменные (являются ли категории дискретными? нужно ли мне что-то другое?)
# sale_date не имеет отсутствующих значений
house["sale_date"] = pd.to_datetime(house["sale_date"]).dt.strftime("%Y-%m-%d")
house["sale_date"] = house["sale_date"].astype("category")
# Замена отсутствующих значений в months_listed
# Все остальные значения уже округлены до 1 десятичного знака
house["months_listed"].fillna(round(np.mean(house["months_listed"]), ndigits = 1), inplace = True)
# Нет отсутствующих значений в bedrooms
# Исправление названий house_type и преобразование house_type в порядковую категорию
# Нет отсутствующих значений в house_type
for i in range(len(house["house_type"])):
if house["house_type"][i] == "Det.":
house["house_type"][i] = "Detached"
elif house["house_type"][i] == "Semi":
house["house_type"][i] = "Semi-Detached"
else:
house["house_type"][i] = "Terraced"
house["house_type"] = house["house_type"].astype("category")
house["house_type"] = pd.Categorical(house["house_type"], ordered = True, categories = ["Terraced", "Semi-Detached", "Detached"])
# Удалить sq.m. из area и округлить до 1 десятичного знака.
house["area"] = house["area"].str.strip("sq.m.").astype(float).round(1)
clean_data = house
Примечание: я использовал цикл for для house_type
вместо метода mapping или replace()
поскольку эти методы исказили значения
.
Ответ или решение
При выборе подходящего типа данных (dtype) для даты, описываемой как "дискретная", важно учесть несколько факторов. В вашем случае, в задании экзамена на платформе DataCamp, дата продажи дома имеет характеристику "дискретная". Давайте разберемся, что это означает и как эффективно обработать дату в контексте данных.
Характеристика "Дискретная"
Вообще говоря, данные могут быть дискретными или непрерывными. В большинстве случаев, даты считаются временными данными, которые имеют свою уникальную природу и обычно работают с типами данных datetime. Однако, в вашей задаче даты обозначены как "дискретные", что может означать необходимость работы с датами как с отдельными точками на временной шкале, а не как с интервалами времени.
Выбор типа данных
В Python и пакете Pandas, существует несколько способов обработки даты:
-
Дата как строка (string): Дата может быть представлена в виде строки, с помощью метода
dt.strftime('%Y-%m-%d')
. Это преобразование делает дату дискретной, позволяя рассматривать каждую дату как уникальную категорию. Однако, это не идеальный подход, если вы планируете выполнять какие-либо вычисления с датой. -
Категориальный тип (category): Ваш код уже включает преобразование даты в категориальный тип данных (
astype('category')
). Это может быть допустимо для решения проблемы классификации дат, поскольку оно позволяет эффективно хранить множество уникальных значений и выполнять операции сравнения. Тем не менее, использование категориального типа данных не всегда является лучшей практикой для работы с датами, если учесть возможную необходимость вычислений. -
Тип datetime в Pandas: Использование
pd.to_datetime()
для преобразования даты в тип datetime является наиболее распространенной практикой, так как позволяет полноценно работать с временными данными (выполнять арифметические операции, фильтрации и т.д.).
Рекомендации
Учитывая вышеизложенное, для решения вашей задачи и выполнения требований дискретных данных, наиболее подходящее решение — всё же оставить дату в виде строкового представления или использовать категориальный тип данных, как и было сделано в вашем коде. Это позволит сохранять уникальность каждого значения даты и соответствовать условиям задания.
Однако, если цель вашего проекта могла измениться и требует выполнения анализа временных рядов, рекомендуется использовать тип datetime, чтобы сохранять функциональность работы с датами.
Заключение
Для достижения наилучших практик работы с данными и соблюдения требований к чистке данных, важно точно интерпретировать контекст задачи. Ваша текущая имплементация представления даты как дискретной переменной через строковое представление или категориальный тип — это обоснованный подход для выполнения поставленных требований.