78 KiB
Унитарное кодирование¶
Преобразование категориального признака в несколько бинарных признаков
Загрузка набора дынных, преобразование данных в числовой формат.¶
import pandas as pd
countries = pd.read_csv(
"data/population.csv", index_col="no"
)
#преобразуем данные в числовой формат, удаляем запятые
countries["Population 2020"] = countries["Population 2020"].apply(
lambda x: int("".join(x.split(",")))
)
countries["Net Change"] = countries["Net Change"].apply(
lambda x: int("".join(x.split(",")))
)
countries["Yearly Change"] = countries["Yearly Change"].apply(
lambda x: float("".join(x.rstrip("%")))
)
countries["Land Area (Km²)"] = countries["Land Area (Km²)"].apply(
lambda x: int("".join(x.split(",")))
)
countries
Унитарное кодирование признаков Пол (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 = ["Small", "Middle", "Big"]
num_bins = 3
hist1, bins1 = np.histogram(
countries["Land Area (Km²)"].fillna(countries["Land Area (Km²)"].median()), bins=num_bins
)
bins1, hist1
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.cut(countries["Land Area (Km²)"], list(bins1)),
],
axis=1,
).head(20)
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.cut(countries["Land Area (Km²)"], list(bins1), labels=labels),
],
axis=1,
).head(20)
Равномерное разделение данных на 3 группы c установкой собственной границы диапазона значений (от 0 до 100)
labels = ["Small", "Middle", "Big"]
bins2 = np.linspace(0, 12000000, 4)
tmp_bins2 = np.digitize(
countries["Land Area (Km²)"].fillna(countries["Land Area (Km²)"].median()), bins2
)
hist2 = np.bincount(tmp_bins2 - 1)
bins2, hist2
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.cut(countries["Land Area (Km²)"], list(bins2)),
],
axis=1,
).head(20)
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.cut(countries["Land Area (Km²)"], list(bins2), labels=labels),
],
axis=1,
).head(20)
Равномерное разделение данных на 3 группы c установкой собственных интервалов (0 - 39, 40 - 60, 61 - 100)
labels2 = ["Dwarf", "Small", "Middle", "Big", "Giant"]
hist3, bins3 = np.histogram(
countries["Land Area (Km²)"].fillna(countries["Land Area (Km²)"].median()),
bins=[0, 1000, 100000, 500000, 3000000, np.inf],
)
bins3, hist3
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.cut(countries["Land Area (Km²)"], list(bins3)),
],
axis=1,
).head(20)
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.cut(countries["Land Area (Km²)"], list(bins3), labels=labels2),
],
axis=1,
).head(20)
Квантильное разделение данных на 5 групп
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.qcut(countries["Land Area (Km²)"], q=5, labels=False),
],
axis=1,
).head(20)
pd.concat(
[
countries["Country (or dependency)"],
countries["Land Area (Km²)"],
pd.qcut(countries["Land Area (Km²)"], q=5, labels=labels2),
],
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
info = pd.read_csv("data/population.csv")
forcast = pd.read_csv("data/forcast.csv")
capitals = pd.read_csv("data/country.csv", encoding="ISO-8859-1")
forcast["Population"] = forcast["Population"].apply(
lambda x: int("".join(x.split(",")))
)
forcast["YearlyPer"] = forcast["YearlyPer"].apply(
lambda x: float("".join(x.rstrip("%")))
)
forcast["Yearly"] = forcast["Yearly"].apply(
lambda x: int("".join(x.split(",")))
)
info = info.drop(
["Migrants (net)", "Fert. Rate", "MedAge", "Urban Pop %", "World Share"], axis=1
)
info["Population 2020"] = info["Population 2020"].apply(
lambda x: int("".join(x.split(",")))
)
info["Yearly Change"] = info["Yearly Change"].apply(
lambda x: float("".join(x.rstrip("%")))
)
info["Net Change"] = info["Net Change"].apply(
lambda x: int("".join(x.split(",")))
)
info["Land Area (Km²)"] = info["Land Area (Km²)"].apply(
lambda x: int("".join(x.split(",")))
)
info, forcast, capitals
Создание сущностей в featuretools¶
Добавление dataframe'ов с данными в EntitySet с указанием параметров: название сущности (таблицы), первичный ключ, категориальные атрибуты (в том числе даты)
es = ft.EntitySet(id="countries")
es = es.add_dataframe(
dataframe_name="countries",
dataframe=info,
index="no",
logical_types={
"Country (or dependency)": Categorical,
},
)
es = es.add_dataframe(
dataframe_name="capitals",
dataframe=capitals,
index="Country/Territory",
logical_types={
"Country/Territory": Categorical,
"Capital": Categorical,
"Continent": Categorical,
},
)
es = es.add_dataframe(
dataframe_name="forcast",
dataframe=forcast,
index="forcast_id",
make_index=True,
logical_types={
"Year": Datetime,
},
)
es
Настройка связей между сущностями featuretools¶
Настройка связей между таблицами на уровне ключей
Связь указывается от родителя к потомкам (таблица-родитель, первичный ключ, таблица-потомок, внешний ключ)
es = es.add_relationship(
"capitals", "Country/Territory", "countries", "Country (or dependency)"
)
es
Автоматическое конструирование признаков с помощью featuretools¶
Библиотека применят различные функции агрегации и трансформации к атрибутам таблицы order_items с учетом отношений
Результат помещается в Dataframe feature_matrix
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_dataframe_name="countries",
max_depth=1,
)
feature_matrix
Полученные признаки¶
Список колонок полученного dataframe'а
feature_defs
Отсечение значений признаков¶
Определение выбросов с помощью boxplot
countries.boxplot(column="Population 2020")
Отсечение данных для признака Возраст, значение которых больше 65 лет
countries_norm = countries.copy()
countries_norm["Population Clip"] = countries_norm["Population 2020"].clip(0, 50000000);
countries_norm[countries_norm["Population 2020"] > 50000000][
["Country (or dependency)", "Population 2020", "Population Clip"]
]
Винсоризация признака Возраст
from scipy.stats.mstats import winsorize
print(countries_norm["Population 2020"].quantile(q=0.95))
countries_norm["PopulationWinsorized"] = winsorize(
countries_norm["Population 2020"].fillna(countries_norm["Population 2020"].mean()),
(0, 0.05),
inplace=False,
)
countries_norm[countries_norm["Population 2020"] > 50000000][
["Country (or dependency)", "Population 2020", "PopulationWinsorized"]
]
Нормализация значений¶
from sklearn import preprocessing
min_max_scaler = preprocessing.MinMaxScaler()
min_max_scaler_2 = preprocessing.MinMaxScaler(feature_range=(-1, 1))
countries_norm["PopulationNorm"] = min_max_scaler.fit_transform(
countries_norm["Population 2020"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population 2020"].shape)
countries_norm["PopulationClipNorm"] = min_max_scaler.fit_transform(
countries_norm["Population Clip"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population 2020"].shape)
countries_norm["PopulationWinsorizedNorm"] = min_max_scaler.fit_transform(
countries_norm["PopulationWinsorized"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population 2020"].shape)
countries_norm["PopulationWinsorizedNorm2"] = min_max_scaler_2.fit_transform(
countries_norm["PopulationWinsorized"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population 2020"].shape)
countries_norm[
[
"Country (or dependency)",
"Population 2020",
"PopulationNorm",
"PopulationClipNorm",
"PopulationWinsorizedNorm",
"PopulationWinsorizedNorm2",
]
]
Стандартизация значений¶
from sklearn import preprocessing
stndart_scaler = preprocessing.StandardScaler()
countries_norm["PopulationStand"] = stndart_scaler.fit_transform(
countries_norm["Population 2020"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population 2020"].shape)
countries_norm["PopulationClipStand"] = stndart_scaler.fit_transform(
countries_norm["Population Clip"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population 2020"].shape)
countries_norm["PopulationWinsorizedStand"] = stndart_scaler.fit_transform(
countries_norm["PopulationWinsorized"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population 2020"].shape)
countries_norm[
[
"Country (or dependency)",
"Population 2020",
"PopulationStand",
"PopulationClipStand",
"PopulationWinsorizedStand",
]
]