123 KiB
Унитарное кодирование¶
Преобразование категориального признака в несколько бинарных признаков
Загрузка набора данных World Population¶
import pandas as pd
countries = pd.read_csv(
"data/world-population-by-country-2020.csv", index_col="no"
)
countries["Population2020"] = countries["Population2020"].apply(
lambda x: int("".join(x.split(",")))
)
countries["Net Change"] = countries["NetChange"].apply(
lambda x: int("".join(x.split(",")))
)
countries["Yearly"] = countries["Yearly"].apply(
lambda x: float("".join(x.rstrip("%")))
)
countries["LandArea"] = countries["LandArea"].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["LandArea"].fillna(countries["LandArea"].median()), bins=num_bins
)
bins1, hist1
pd.concat(
[countries["LandArea"], pd.cut(countries["LandArea"], list(bins1))], axis=1
).head(20)
pd.concat([countries["LandArea"], pd.cut(countries["LandArea"], 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["LandArea"].fillna(countries["LandArea"].median()), bins2
)
hist2 = np.bincount(tmp_bins2 - 1)
bins2, hist2
pd.concat([countries["LandArea"], pd.cut(countries["LandArea"], list(bins2))], axis=1).head(20)
pd.concat(
[countries["LandArea"], pd.cut(countries["LandArea"], 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["LandArea"].fillna(countries["LandArea"].median()), bins=[0, 1000, 100000, 500000, 3000000, np.inf]
)
bins3, hist3
pd.concat([countries["LandArea"], pd.cut(countries["LandArea"], list(bins3))], axis=1).head(20)
pd.concat(
[countries["LandArea"], pd.cut(countries["LandArea"], list(bins3), labels=labels2)],
axis=1,
).head(20)
Квантильное разделение данных на 5 групп
pd.concat([countries["LandArea"], pd.qcut(countries["LandArea"], q=5, labels=False)], axis=1).head(20)
pd.concat([countries["LandArea"], pd.qcut(countries["LandArea"], 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
Загрузка данных¶
import featuretools as ft
from woodwork.logical_types import Categorical, Datetime
info = pd.read_csv("data/world-population-by-country-2020.csv")
forcast = pd.read_csv("data/world-population-forcast-2020-2050.csv")
capitals = pd.read_csv("data/countries-continents-capitals.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", "FertRate", "MedAge", "UrbanPop", "WorldShare"], axis=1)
info["Population2020"] = info["Population2020"].apply(
lambda x: int("".join(x.split(",")))
)
info["Yearly"] = info["Yearly"].apply(
lambda x: float("".join(x.rstrip("%")))
)
info["NetChange"] = info["NetChange"].apply(
lambda x: int("".join(x.split(",")))
)
info["LandArea"] = info["LandArea"].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": Categorical,
},
)
es = es.add_dataframe(
dataframe_name="capitals",
dataframe=capitals,
index="Country",
logical_types={
"Country": 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", "countries", "Country")
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="Population2020")
Отсечение данных для признака Население, значение которых больше 50000000
countries_norm = countries.copy()
countries_norm["PopulationClip"] = countries_norm["Population2020"].clip(0, 50000000)
countries_norm[countries_norm["Population2020"] > 50000000][
["Country", "Population2020", "PopulationClip"]
]
Винсоризация признака Возраст
from scipy.stats.mstats import winsorize
print(countries_norm["Population2020"].quantile(q=0.95))
countries_norm["PopulationWinsorized"] = winsorize(
countries_norm["Population2020"].fillna(countries_norm["Population2020"].mean()),
(0, 0.05),
inplace=False,
)
countries_norm[countries_norm["Population2020"] > 50000000][
["Country", "Population2020", "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["Population2020"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population2020"].shape)
countries_norm["PopulationClipNorm"] = min_max_scaler.fit_transform(
countries_norm["PopulationClip"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population2020"].shape)
countries_norm["PopulationWinsorizedNorm"] = min_max_scaler.fit_transform(
countries_norm["PopulationWinsorized"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population2020"].shape)
countries_norm["PopulationWinsorizedNorm2"] = min_max_scaler_2.fit_transform(
countries_norm["PopulationWinsorized"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population2020"].shape)
countries_norm[
[
"Country",
"Population2020",
"PopulationNorm",
"PopulationClipNorm",
"PopulationWinsorizedNorm",
"PopulationWinsorizedNorm2",
]
]
Стандартизация значений¶
from sklearn import preprocessing
stndart_scaler = preprocessing.StandardScaler()
countries_norm["PopulationStand"] = stndart_scaler.fit_transform(
countries_norm["Population2020"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population2020"].shape)
countries_norm["PopulationClipStand"] = stndart_scaler.fit_transform(
countries_norm["PopulationClip"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population2020"].shape)
countries_norm["PopulationWinsorizedStand"] = stndart_scaler.fit_transform(
countries_norm["PopulationWinsorized"].to_numpy().reshape(-1, 1)
).reshape(countries_norm["Population2020"].shape)
countries_norm[
[
"Country",
"Population2020",
"PopulationStand",
"PopulationClipStand",
"PopulationWinsorizedStand",
]
]