160 KiB
Загрузка набора данных Titanic¶
import pandas as pd
titanic = pd.read_csv("data/titanic.csv", index_col="PassengerId")
titanic
Унитарное кодирование¶
Преобразование категориального признака в несколько бинарных признаков
Унитарное кодирование признаков Пол (Sex) и Порт посадки (Embarked)¶
Кодирование
from sklearn.preprocessing import OneHotEncoder
import numpy as np
encoder = OneHotEncoder(sparse_output=False, drop="first")
encoded_values = encoder.fit_transform(titanic[["Embarked", "Sex"]])
encoded_columns = encoder.get_feature_names_out(["Embarked", "Sex"])
encoded_values_df = pd.DataFrame(encoded_values, columns=encoded_columns)
encoded_values_df
Добавление признаков в исходный Dataframe
titanic = pd.concat([titanic, encoded_values_df], axis=1)
titanic
Дискретизация признаков¶
Равномерное разделение данных на 3 группы
labels = ["young", "middle-aged", "old"]
num_bins = 3
hist1, bins1 = np.histogram(titanic["Age"].fillna(titanic["Age"].median()), bins=num_bins)
bins1, hist1
pd.concat([titanic["Age"], pd.cut(titanic["Age"], list(bins1))], axis=1).head(20)
pd.concat([titanic["Age"], pd.cut(titanic["Age"], list(bins1), labels=labels)], axis=1).head(20)
Равномерное разделение данных на 3 группы c установкой собственной границы диапазона значений (от 0 до 100)
bins2 = np.linspace(0, 100, 4)
tmp_bins2 = np.digitize(titanic["Age"].fillna(titanic["Age"].median()), bins2)
hist2 = np.bincount(tmp_bins2 - 1)
bins2, hist2
pd.concat([titanic["Age"], pd.cut(titanic["Age"], list(bins2))], axis=1).head(20)
pd.concat([titanic["Age"], pd.cut(titanic["Age"], list(bins2), labels=labels)], axis=1).head(20)
Равномерное разделение данных на 3 группы c установкой собственных интервалов (0 - 39, 40 - 60, 61 - 100)
hist3, bins3 = np.histogram(
titanic["Age"].fillna(titanic["Age"].median()), bins=[0, 40, 60, 100]
)
bins3, hist3
pd.concat([titanic["Age"], pd.cut(titanic["Age"], list(bins3))], axis=1).head(20)
pd.concat([titanic["Age"], pd.cut(titanic["Age"], list(bins3), labels=labels)], axis=1).head(20)
Квантильное разделение данных на 3 группы
pd.concat([titanic["Age"], pd.qcut(titanic["Age"], q=3, labels=False)], axis=1).head(20)
pd.concat([titanic["Age"], pd.qcut(titanic["Age"], q=3, labels=labels)], axis=1).head(20)
Пример конструирования признаков на основе существующих¶
Title - обращение к пассажиру (Mr, Mrs, Miss)
Is_married - замужняя ли женщина
Cabin_type - палуба (тип каюты)
titanic_cl = titanic.drop(
["Embarked_Q", "Embarked_S", "Embarked_nan", "Sex_male"], axis=1, errors="ignore"
)
titanic_cl = titanic_cl.dropna()
titanic_cl["Title"] = [
i.split(",")[1].split(".")[0].strip() for i in titanic_cl["Name"]
]
titanic_cl["Is_married"] = [1 if i == "Mrs" else 0 for i in titanic_cl["Title"]]
titanic_cl["Cabin_type"] = [i[0] for i in titanic_cl["Cabin"]]
titanic_cl
Пример использования библиотеки Featuretools для автоматического конструирования (синтеза) признаков¶
https://featuretools.alteryx.com/en/stable/getting_started/using_entitysets.html
Загрузка данных¶
За основу был взят набор данных "Ecommerce Orders Data Set" из Kaggle
Используется только 100 первых заказов и связанные с ними объекты
https://www.kaggle.com/datasets/sangamsharmait/ecommerce-orders-data-analysis
import featuretools as ft
from woodwork.logical_types import Categorical, Datetime
customers = pd.read_csv("data/orders/customers.csv")
sellers = pd.read_csv("data/orders/sellers.csv")
products = pd.read_csv("data/orders/products.csv")
orders = pd.read_csv("data/orders/orders.csv")
orders.fillna({"order_delivered_carrier_date": pd.to_datetime(
"1900-01-01 00:00:00"
)}, inplace=True)
orders.fillna(
{"order_delivered_customer_date": pd.to_datetime("1900-01-01 00:00:00")},
inplace=True,
)
order_items = pd.read_csv("data/orders/order_items.csv")
Создание сущностей в featuretools¶
Добавление dataframe'ов с данными в EntitySet с указанием параметров: название сущности (таблицы), первичный ключ, категориальные атрибуты (в том числе даты)
es = ft.EntitySet(id="orders")
es = es.add_dataframe(
dataframe_name="customers",
dataframe=customers,
index="customer_id",
logical_types={
"customer_unique_id": Categorical,
"customer_zip_code_prefix": Categorical,
"customer_city": Categorical,
"customer_state": Categorical,
},
)
es = es.add_dataframe(
dataframe_name="sellers",
dataframe=sellers,
index="seller_id",
logical_types={
"seller_zip_code_prefix": Categorical,
"seller_city": Categorical,
"seller_state": Categorical,
},
)
es = es.add_dataframe(
dataframe_name="products",
dataframe=products,
index="product_id",
logical_types={
"product_category_name": Categorical,
"product_name_lenght": Categorical,
"product_description_lenght": Categorical,
"product_photos_qty": Categorical,
},
)
es = es.add_dataframe(
dataframe_name="orders",
dataframe=orders,
index="order_id",
logical_types={
"order_status": Categorical,
"order_purchase_timestamp": Datetime,
"order_approved_at": Datetime,
"order_delivered_carrier_date": Datetime,
"order_delivered_customer_date": Datetime,
"order_estimated_delivery_date": Datetime,
},
)
es = es.add_dataframe(
dataframe_name="order_items",
dataframe=order_items,
index="orderitem_id",
make_index=True,
logical_types={"shipping_limit_date": Datetime},
)
es
Настройка связей между сущностями featuretools¶
Настройка связей между таблицами на уровне ключей
Связь указывается от родителя к потомкам (таблица-родитель, первичный ключ, таблица-потомок, внешний ключ)
es = es.add_relationship("customers", "customer_id", "orders", "customer_id")
es = es.add_relationship("orders", "order_id", "order_items", "order_id")
es = es.add_relationship("products", "product_id", "order_items", "product_id")
es = es.add_relationship("sellers", "seller_id", "order_items", "seller_id")
es
Автоматическое конструирование признаков с помощью featuretools¶
Библиотека применят различные функции агрегации и трансформации к атрибутам таблицы order_items с учетом отношений
Результат помещается в Dataframe feature_matrix
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_dataframe_name="order_items",
agg_primitives=["mean", "count", "mode", "any"],
trans_primitives=["hour", "weekday"],
max_depth=2,
)
feature_matrix
Полученные признаки¶
Список колонок полученного dataframe'а
feature_defs
Отсечение значений признаков¶
Определение выбросов с помощью boxplot
titanic.boxplot(column="Age")
Отсечение данных для признака Возраст, значение которых больше 65 лет
titanic_norm = titanic.copy()
titanic_norm["AgeClip"] = titanic["Age"].clip(0, 65);
titanic_norm[titanic_norm["Age"] > 65][["Name", "Age", "AgeClip"]]
Винсоризация признака Возраст
from scipy.stats.mstats import winsorize
print(titanic_norm["Age"].quantile(q=0.95))
titanic_norm["AgeWinsorize"] = winsorize(
titanic_norm["Age"].fillna(titanic_norm["Age"].mean()), (0, 0.05), inplace=False
)
titanic_norm[titanic_norm["Age"] > 65][["Name", "Age", "AgeWinsorize"]]
Нормализация значений¶
from sklearn import preprocessing
min_max_scaler = preprocessing.MinMaxScaler()
min_max_scaler_2 = preprocessing.MinMaxScaler(feature_range=(-1, 1))
titanic_norm["AgeNorm"] = min_max_scaler.fit_transform(
titanic_norm["Age"].to_numpy().reshape(-1, 1)
).reshape(titanic_norm["Age"].shape)
titanic_norm["AgeClipNorm"] = min_max_scaler.fit_transform(
titanic_norm["AgeClip"].to_numpy().reshape(-1, 1)
).reshape(titanic_norm["Age"].shape)
titanic_norm["AgeWinsorizeNorm"] = min_max_scaler.fit_transform(
titanic_norm["AgeWinsorize"].to_numpy().reshape(-1, 1)
).reshape(titanic_norm["Age"].shape)
titanic_norm["AgeWinsorizeNorm2"] = min_max_scaler_2.fit_transform(
titanic_norm["AgeWinsorize"].to_numpy().reshape(-1, 1)
).reshape(titanic_norm["Age"].shape)
titanic_norm[
["Name", "Age", "AgeNorm", "AgeClipNorm", "AgeWinsorizeNorm", "AgeWinsorizeNorm2"]
].head(20)
Стандартизация значений¶
from sklearn import preprocessing
stndart_scaler = preprocessing.StandardScaler()
titanic_norm["AgeStand"] = stndart_scaler.fit_transform(
titanic_norm["Age"].to_numpy().reshape(-1, 1)
).reshape(titanic_norm["Age"].shape)
titanic_norm["AgeClipStand"] = stndart_scaler.fit_transform(
titanic_norm["AgeClip"].to_numpy().reshape(-1, 1)
).reshape(titanic_norm["Age"].shape)
titanic_norm["AgeWinsorizeStand"] = stndart_scaler.fit_transform(
titanic_norm["AgeWinsorize"].to_numpy().reshape(-1, 1)
).reshape(titanic_norm["Age"].shape)
titanic_norm[["Name", "Age", "AgeStand", "AgeClipStand", "AgeWinsorizeStand"]].head(20)