813 KiB
Лабораторная 2¶
Первый датасет: Набор данных для анализа и прогнозирования сердечного приступа (https://www.kaggle.com/datasets/kamilpytlak/personal-key-indicators-of-heart-disease)
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df_heart = pd.read_csv("..\\static\\csv\\heart_2020_cleaned.csv")
print(df_heart.columns)
Столбцы на русском:
HeartDisease - сердечный приступ
BMI - ИМТ
Smoking - курящий ли человек
AlcoholDrinking - выпивающий ли человек
Stroke - был ли инсульт
PhysicalHealth - физическое здоровье
MentalHealth - ментальное здоровье
DiffWalking - проблемы с ходьбой
Sex - пол
AgeCategory - возрастная категория
Race - раса
Diabetic - диабетик ли человек
PhysicalActivity - физическая активность
GenHealth - общее здоровье
SleepTime - время сна
Asthma - астматик ли человек
KidneyDisease - нефропатия
SkinCancer - рак кожи
df_heart.info()
df_heart.head()
Объект наблюдения: состояние человека
Атрибуты объектов: сердечная недостаточность, ИМТ, курящий человек или нет, выпивающий человек или нет, был ли инсульт у человека и т.д.
mean_menthalhealth = df_heart.groupby('AgeCategory')['SleepTime'].mean().reset_index()
plt.figure(figsize=(14, 6))
plt.plot(mean_menthalhealth['AgeCategory'], mean_menthalhealth['SleepTime'], marker='.')
plt.title("Диаграмма 1")
plt.xlabel("Возрастная группа")
plt.ylabel("Время сна")
plt.show()
Между атрибутами присутствует связь. Пример, на диаграмме 1 - связь между возрастной группой и временем сна
Примеры бизнес-целей:
1. Прогнозирование инсульта на основе ИМТ.
2. Наблюдение за изменением времени сна в зависимости от возраста.
Эффект для бизнеса: влияние количества сна на здоровье, влияние ИМТ на здоровье, влияние возраста на инсульты
Цели технического проекта:
1. Первая бизнес-цель: вход - ИМТ, целевой признак - инсульт.
2. Вторая бизнес-цель: вход - возрастная группа, целевой признак - время сна.
Проверка на выбросы
null_values = df_heart.isnull().sum()
print("Пустые значения по столбцам:")
print(null_values)
duplicates = df_heart.duplicated().sum()
print(f"\nКоличество дубликатов: {duplicates}")
print("\nСтатистический обзор данных:")
df_heart.describe()
На основе полученной информации видно, что пустых данных нет, но есть дубликаты. Удалим их и проверим данные на выбросы:
cleaned_df = df_heart.drop_duplicates()
for column in df_heart.select_dtypes(include=[np.number]).columns:
skewness = df_heart[column].skew()
print(f"\nКоэффициент асимметрии для столбца '{column}': {skewness}")
Выбросы незначительные. Очистка данных от шумов
plt.figure(figsize=(10, 6))
plt.scatter(cleaned_df['BMI'], cleaned_df['PhysicalHealth'])
plt.xlabel('ИМТ')
plt.ylabel('Физическое здоровье')
plt.title('Диаграмма рассеивания перед чисткой')
plt.show()
Q1 = cleaned_df["BMI"].quantile(0.25)
Q3 = cleaned_df["BMI"].quantile(0.75)
IQR = Q3 - Q1
threshold = 1.5 * IQR
lower_bound = Q1 - threshold
upper_bound = Q3 + threshold
outliers = (cleaned_df["BMI"] < lower_bound) | (cleaned_df["BMI"] > upper_bound)
print("Выбросы в датасете:")
print(cleaned_df[outliers])
median_score = cleaned_df["BMI"].median()
cleaned_df.loc[outliers, "BMI"] = median_score
plt.figure(figsize=(10, 6))
plt.scatter(cleaned_df['BMI'], cleaned_df['PhysicalHealth'])
plt.xlabel('ИМТ')
plt.ylabel('Физическое здоровье')
plt.title('Диаграмма рассеивания после чистки')
plt.show()
Разбиение набора данных на обучающую, контрольную и тестовую выборки
from sklearn.model_selection import train_test_split
train_df, test_df = train_test_split(cleaned_df, test_size=0.2, random_state=42)
train_df, val_df = train_test_split(train_df, test_size=0.25, random_state=42)
print("Размер обучающей выборки:", len(train_df))
print("Размер контрольной выборки:", len(val_df))
print("Размер тестовой выборки:", len(test_df))
def check_balance(df, name):
counts = df['BMI'].value_counts()
print(f"Распределение ИМТ в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
check_balance(val_df, "контрольной выборке")
check_balance(test_df, "тестовой выборке")
Оверсемплинг и андерсемплинг
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
def binning(target, bins):
return pd.qcut(target, q=bins, labels=False)
train_df['BMI_binned'] = binning(train_df['BMI'], bins=2)
val_df['BMI_binned'] = binning(val_df['BMI'], bins=2)
test_df['BMI_binned'] = binning(test_df['BMI'], bins=2)
def oversample(df, target_column):
X = df.drop(target_column, axis=1)
y = df[target_column]
oversampler = RandomOverSampler(random_state=42)
x_resampled, y_resampled = oversampler.fit_resample(X, y)
resampled_df = pd.concat([x_resampled, y_resampled], axis=1)
return resampled_df
def undersample(df, target_column):
X = df.drop(target_column, axis=1)
y = df[target_column]
undersampler = RandomUnderSampler(random_state=42)
x_resampled, y_resampled = undersampler.fit_resample(X, y)
resampled_df = pd.concat([x_resampled, y_resampled], axis=1)
return resampled_df
train_df_oversampled = oversample(train_df, 'BMI_binned')
val_df_oversampled = oversample(val_df, 'BMI_binned')
test_df_oversampled = oversample(test_df, 'BMI_binned')
train_df_undersampled = undersample(train_df, 'BMI_binned')
val_df_undersampled = undersample(val_df, 'BMI_binned')
test_df_undersampled = undersample(test_df, 'BMI_binned')
print("Оверсэмплинг:")
check_balance(train_df_oversampled, "обучающей выборке")
check_balance(val_df_oversampled, "контрольной выборке")
check_balance(test_df_oversampled, "тестовой выборке")
print("Андерсэмплинг:")
check_balance(train_df_undersampled, "обучающей выборке")
check_balance(val_df_undersampled, "контрольной выборке")
check_balance(test_df_undersampled, "тестовой выборке")
Датасет: Цены на мобильные устройства (https://www.kaggle.com/datasets/dewangmoghe/mobile-phone-price-prediction)
df_phones = pd.read_csv("..\\static\\csv\\mobile-phone-price-prediction.csv")
print(df_phones.columns)
Столбцы на русском:
Unnamed: 0 - идентификатор
Name - Модель
Rating - Рейтинг
Spec_score - Оценка характеристик
No_of_sim - Доступние сим-карты
Ram - Объем оперативной памяти
Battery - Батарея
Display - Размер дисплея
Camera - Камера
External_Memory - Внешняя память
Android_version - Версия Android
Price - Цена
company - Фирма
Inbuilt_memory - Встроенная память
fast_charging - Быстрая зарядка
Screen_resolution - Разрешение экрана
Processor - Процессор
Processor_name - Название процессора
df_phones.info()
df_phones.head()
Объект наблюдения: телефон
Атрибуты объектов: название модели, рейтинг, оценка характеристик, сим-карты, оперативная память и т.д.
plt.figure(figsize=(14, 6))
plt.scatter(df_phones['company'].str.lower(), df_phones['Spec_score'])
plt.xlabel('Фирма')
plt.ylabel('Оценка характеристик')
plt.xticks(rotation=45)
plt.title('Диаграмма 1')
plt.show()
Между атрибутами присутствует связь. Пример, на диаграмме 1 - связь между фирмой и оценкой характеристик
Примеры бизнес-целей:
1. Прогнозирование цен на основе оценки характеристик
2. Прогнозирование оценки характеристик на основе фирмы и цены
Эффект для бизнеса: влияние фирмы на цену, влияние характеристик на рейтинг
Цели технического проекта:
1. Первая бизнес-цель: вход - оценка характеристик, целевой признак - цена.
2. Вторая бизнес-цель: вход - фирма и цена, целевой признак - оценка характеристик.
Проверка на выбросы
null_values = df_phones.isnull().sum()
print("Пустые значения по столбцам:")
print(null_values)
duplicates = df_phones.duplicated().sum()
print(f"\nКоличество дубликатов: {duplicates}")
print("\nСтатистический обзор данных:")
df_phones.describe()
Видим, что есть пустые данные, но нет дубликатов. Удаляем их
def drop_missing_values(dataframe, name):
before_shape = dataframe.shape
cleaned_dataframe = dataframe.dropna()
after_shape = cleaned_dataframe.shape
print(f"В наборе данных '{name}' было удалено {before_shape[0] - after_shape[0]} строк с пустыми значениями.")
return cleaned_dataframe
cleaned_df = drop_missing_values(df_phones, "Phones")
Рассчитаем коэффицент ассиметрии
for column in df_phones.select_dtypes(include=[np.number]).columns:
skewness = df_phones[column].skew()
print(f"\nКоэффициент асимметрии для столбца '{column}': {skewness}")
Видим, что выбросы незначительные
Очистка данных от шумов
plt.figure(figsize=(10, 6))
plt.scatter(cleaned_df['company'].str.lower(), cleaned_df['Spec_score'])
plt.xlabel('Фирма')
plt.ylabel('Оценка характеристик')
plt.xticks(rotation=45)
plt.title('Диаграмма рассеивания перед чисткой')
plt.show()
Q1 = cleaned_df["Spec_score"].quantile(0.25)
Q3 = cleaned_df["Spec_score"].quantile(0.75)
IQR = Q3 - Q1
threshold = 1.5 * IQR
lower_bound = Q1 - threshold
upper_bound = Q3 + threshold
outliers = (cleaned_df["Spec_score"] < lower_bound) | (cleaned_df["Spec_score"] > upper_bound)
print("Выбросы в датасете:")
print(cleaned_df[outliers])
median_score = cleaned_df["Spec_score"].median()
cleaned_df.loc[outliers, "Spec_score"] = median_score
plt.figure(figsize=(10, 6))
plt.scatter(cleaned_df['company'].str.lower(), cleaned_df['Spec_score'])
plt.xlabel('Фирма')
plt.ylabel('Оценка характеристик')
plt.xticks(rotation=45)
plt.title('Диаграмма рассеивания после чистки')
plt.show()
Разбиение на выборки
train_df, test_df = train_test_split(cleaned_df, test_size=0.2, random_state=42)
train_df, val_df = train_test_split(train_df, test_size=0.25, random_state=42)
print("Размер обучающей выборки:", len(train_df))
print("Размер контрольной выборки:", len(val_df))
print("Размер тестовой выборки:", len(test_df))
print()
def check_balance(df, name):
counts = df['Spec_score'].value_counts()
print(f"Распределение оценки характеристик в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
check_balance(val_df, "контрольной выборке")
check_balance(test_df, "тестовой выборке")
Оверсемплинг и андерсемплинг
train_df_oversampled = oversample(train_df, 'Spec_score')
val_df_oversampled = oversample(val_df, 'Spec_score')
test_df_oversampled = oversample(test_df, 'Spec_score')
train_df_undersampled = undersample(train_df, 'Spec_score')
val_df_undersampled = undersample(val_df, 'Spec_score')
test_df_undersampled = undersample(test_df, 'Spec_score')
print("Оверсэмплинг:")
check_balance(train_df_oversampled, "обучающей выборке")
check_balance(val_df_oversampled, "контрольной выборке")
check_balance(test_df_oversampled, "тестовой выборке")
print("Андерсэмплинг:")
check_balance(train_df_undersampled, "обучающей выборке")
check_balance(val_df_undersampled, "контрольной выборке")
check_balance(test_df_undersampled, "тестовой выборке")
Датасет: "Удаленная работа и ментальное здоровье" (https://www.kaggle.com/datasets/waqi786/remote-work-and-mental-health)
df_remotework = pd.read_csv("..\\static\\csv\\Impact_of_Remote_Work_on_Mental_Health.csv")
print(df_remotework.columns)
Столбцы на русском:
Employee_ID - идентификатор
Age - возраст
Gender - гендер
Job_Role - специальность
Industry - образование
Years_of_Experience - опыт
Work_Location - место работы
Hours_Worked_Per_Week - количество часов работы в неделю
Number_of_Virtual_Meetings - количество виртуальных встреч
Work_Life_Balance_Rating - рейтинг баланса между работой и жизнью
Stress_Level - уровень стресса
Mental_Health_Condition - состояние ментального здоровья
Access_to_Mental_Health_Resources - доступ к ресурсам по психическому здоровью
Productivity_Change - изменение продуктивности
Social_Isolation_Rating - рейтинг социальной изоляции
Satisfaction_with_Remote_Work - удовольствие от удаленной работы
Company_Support_for_Remote_Work - поддержка компании удаленной работы
Physical_Activity - физическая активность
Sleep_Quality - качество сна
Region - регион
df_remotework.info()
df_remotework.head()
Объект наблюдения: работник
Атрибуты объектов: возраст, гендер, специальность, образование и т.д.
mean_isolation_rating = df_remotework.groupby('Work_Location')['Social_Isolation_Rating'].mean().reset_index()
plt.figure(figsize=(14, 6))
plt.plot(mean_isolation_rating['Work_Location'], mean_isolation_rating['Social_Isolation_Rating'])
plt.title("Диаграмма 1")
plt.xlabel("Место работы")
plt.ylabel("Рейтинг социальной изоляции")
plt.show()
Между атрибутами присутствует связь. Пример, на диаграмме 1 - связь между местом работы и рейтингом социальной изоляции
Примеры бизнес-целей:
1. Прогнозирование изменения продуктивности на основе опыта работы и уровня стресса
2. Прогнозирование ментального состояния на основе рейтинга баланса между работой и жизнью
Эффект для бизнеса: влияние ментального состояния на продуктивность, влияние качества сна и количества часов работы в неделю на ментальное состояние
Цели технического проекта:
1. Первая бизнес-цель: вход - опыт работы, уровень стресса, целевой признак - изменение продуктивности.
2. Вторая бизнес-цель: вход - рейтинг баланса между работой и жизнью, целевой признак - ментальное состояние.
Проверим на выбросы
null_values = df_remotework.isnull().sum()
print("Пустые значения по столбцам:")
print(null_values)
duplicates = df_remotework.duplicated().sum()
print(f"\nКоличество дубликатов: {duplicates}")
print("\nСтатистический обзор данных:")
df_remotework.describe()
Видим, что есть пустые данные, но нет дубликатов. Удаляем их
cleaned_df_remotework = drop_missing_values(df_remotework, "RemoteWork")
Рассчитаем коэффицент ассиметрии
for column in cleaned_df_remotework.select_dtypes(include=[np.number]).columns:
skewness = cleaned_df_remotework[column].skew()
print(f"\nКоэффициент асимметрии для столбца '{column}': {skewness}")
Видим, что выбросы незначительные
Очистка данных от шумов
plt.figure(figsize=(10, 6))
plt.scatter(cleaned_df_remotework['Age'], cleaned_df_remotework['Number_of_Virtual_Meetings'])
plt.xlabel('Возраст')
plt.ylabel('Количество виртуальных встреч')
plt.xticks(rotation=45)
plt.title('Диаграмма рассеивания перед чисткой')
plt.show()
Q1 = cleaned_df_remotework["Hours_Worked_Per_Week"].quantile(0.25)
Q3 = cleaned_df_remotework["Hours_Worked_Per_Week"].quantile(0.75)
IQR = Q3 - Q1
threshold = 1.5 * IQR
lower_bound = Q1 - threshold
upper_bound = Q3 + threshold
outliers = (cleaned_df_remotework["Hours_Worked_Per_Week"] < lower_bound) | (cleaned_df_remotework["Hours_Worked_Per_Week"] > upper_bound)
print("Выбросы в датасете:")
print(cleaned_df[outliers])
median_score = cleaned_df_remotework["Hours_Worked_Per_Week"].median()
cleaned_df_remotework.loc[outliers, "Hours_Worked_Per_Week"] = median_score
plt.figure(figsize=(10, 6))
plt.scatter(cleaned_df_remotework['Age'], cleaned_df_remotework['Number_of_Virtual_Meetings'])
plt.xlabel('Возраст')
plt.ylabel('Количество виртуальных встреч')
plt.xticks(rotation=45)
plt.title('Диаграмма рассеивания после чистки')
plt.show()
Шумов нет
Разбиение на выборки
train_df, test_df = train_test_split(cleaned_df_remotework, test_size=0.2, random_state=42)
train_df, val_df = train_test_split(train_df, test_size=0.25, random_state=42)
print("Размер обучающей выборки:", len(train_df))
print("Размер контрольной выборки:", len(val_df))
print("Размер тестовой выборки:", len(test_df))
print()
def check_balance(df, name):
counts = df['Hours_Worked_Per_Week'].value_counts()
print(f"Распределение оценки характеристик в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
check_balance(val_df, "контрольной выборке")
check_balance(test_df, "тестовой выборке")
Оверсемплинг и андерсемплинг
train_df_oversampled = oversample(train_df, 'Hours_Worked_Per_Week')
val_df_oversampled = oversample(val_df, 'Hours_Worked_Per_Week')
test_df_oversampled = oversample(test_df, 'Hours_Worked_Per_Week')
train_df_undersampled = undersample(train_df, 'Hours_Worked_Per_Week')
val_df_undersampled = undersample(val_df, 'Hours_Worked_Per_Week')
test_df_undersampled = undersample(test_df, 'Hours_Worked_Per_Week')
print("Оверсэмплинг:")
check_balance(train_df_oversampled, "обучающей выборке")
check_balance(val_df_oversampled, "контрольной выборке")
check_balance(test_df_oversampled, "тестовой выборке")
print("Андерсэмплинг:")
check_balance(train_df_undersampled, "обучающей выборке")
check_balance(val_df_undersampled, "контрольной выборке")
check_balance(test_df_undersampled, "тестовой выборке")