565 KiB
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from sklearn.model_selection import train_test_split
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
Diamonds Prices 2022¶
В данном наборе данных представлена цена на алмазы. Проблемная область: ценообразование бриллиантов Объект наблюдения: бриллиант Атрибуты: идентификатор, вес, качество огранки, цвет, чистота, общая глубина, ширина верхней грани, цена, длина, ширина, высота. Бизнес-цели: Повышение эффективности маркетинговых кампаний: Цель: Использование данных о бриллиантах для разработки целевых маркетинговых кампаний, направленных на конкретные сегменты рынка.
df = pd.read_csv("..//static//csv//DiamondsPrices2022.csv")
print(df.columns)
plt.figure(figsize=(10, 6))
sns.boxplot(x=df['carat'])
plt.title('Box Plot для carat')
plt.xlabel('carat')
plt.show()
# Визуализация данных после обработки
plt.figure(figsize=(10, 6))
plt.scatter(df["price"], df["carat"])
plt.xlabel("price")
plt.ylabel("carat")
plt.title("Scatter Plot of Price vs Carat")
plt.show()
Удаление строк с пустыми значениями
df_cleaned = df.dropna()
Разбиение набора данных на обучающую, контрольную и тестовую выборки
# Разделение на обучающую и тестовую выборки
train_df, test_df = train_test_split(df_cleaned, 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['price'].value_counts()
print(f"Распределение price в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
check_balance(val_df, "контрольной выборке")
check_balance(test_df, "тестовой выборке")
Выполним овер- и андер- слемпинг.
def oversample(df):
X = df.drop("price", axis=1)
y = df["price"]
oversampler = RandomOverSampler(random_state=42)
X_resampled, y_resampled = oversampler.fit_resample(X, y) # type: ignore
resampled_df = pd.concat([X_resampled, y_resampled], axis=1)
return resampled_df
train_df_oversampled = oversample(train_df)
val_df_oversampled = oversample(val_df)
test_df_oversampled = oversample(test_df)
check_balance(train_df_oversampled, "обучающей выборке после oversampling")
check_balance(val_df_oversampled, "контрольной выборке после oversampling")
check_balance(test_df_oversampled, "тестовой выборке после oversampling")
def undersample(df):
X = df.drop('price', axis=1)
y = df['price']
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_undersampled = undersample(train_df)
val_df_undersampled = undersample(val_df)
test_df_undersampled = undersample(test_df)
check_balance(train_df_undersampled, "обучающей выборке после undersampling")
check_balance(val_df_undersampled, "контрольной выборке после undersampling")
check_balance(test_df_undersampled, "тестовой выборке после undersampling")
14,400 Classic Rock Tracks (with Spotify Data)¶
Этот набор данных, содержащий 1200 уникальных альбомов и 14 400 треков. Каждый трек каталогизирован с 18 столбцами данных, такие как название трека, исполнитель, альбом и год выпуска. Бизнес-цель: улучшение стратегии маркетинга и продвижения музыкальных треков, создание алгоритмов, которые будут рекомендовать пользователям музыку на основе их предпочтений. Цель технического проекта: Разработать и внедрить систему рекомендаций, которая будет предсказывать и рекомендовать пользователям музыкальные треки на основе их предпочтений и поведения. Входные данные: Данные о пользователях: Идентификатор пользователя, история прослушиваний, оценки треков, время прослушивания, частота прослушивания. Данные о треках: Атрибуты треков (название, исполнитель, альбом, год, длительность, танцевальность, энергичность, акустичность и т.д.). Данные о взаимодействии: Время и частота взаимодействия пользователя с определенными треками. Целевой признак: Рекомендации: Булева переменная, указывающая, должен ли конкретный трек быть рекомендован пользователю (1 - рекомендуется, 0 - не рекомендуется).
Выгрузка данных из csv файла "Данные о клиентах" в датафрейм
df = pd.read_csv("..//static//csv//UltimateClassicRock.csv")
print(df.columns)
Анализируем датафрейм при помощи "ящика с усами". Есть смещение в сторону меньших значений, это можно исправить при помощи oversampling и undersampling.
# Box plot для столбца 'Popularity'
plt.figure(figsize=(10, 6))
sns.boxplot(x=df['Popularity'])
plt.title('Box Plot для Popularity')
plt.xlabel('Popularity')
plt.show()
Решим проблему пустых значений при помощи удаления таких строк.
df_cleaned = df.dropna()
Разбиение набора данных на обучающую, контрольную и тестовую выборки
# Разделение на обучающую и тестовую выборки
train_df, test_df = train_test_split(df_cleaned, 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['Popularity'].value_counts()
print(f"Распределение Popularity в {name}:")
print(counts)
print()
check_balance(train_df, "обучающей выборке")
check_balance(val_df, "контрольной выборке")
check_balance(test_df, "тестовой выборке")
Выполним овер- и андер- слемпинг.
def oversample(df):
X = df.drop('Popularity', axis=1)
y = df['Popularity']
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
train_df_oversampled = oversample(train_df)
val_df_oversampled = oversample(val_df)
test_df_oversampled = oversample(test_df)
check_balance(train_df_oversampled, "обучающей выборке после oversampling")
check_balance(val_df_oversampled, "контрольной выборке после oversampling")
check_balance(test_df_oversampled, "тестовой выборке после oversampling")
def undersample(df):
X = df.drop('Popularity', axis=1)
y = df['Popularity']
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_undersampled = undersample(train_df)
val_df_undersampled = undersample(val_df)
test_df_undersampled = undersample(test_df)
check_balance(train_df_undersampled, "обучающей выборке после undersampling")
check_balance(val_df_undersampled, "контрольной выборке после undersampling")
check_balance(test_df_undersampled, "тестовой выборке после undersampling")
Car Price Prediction Challenge¶
В данном наборе данных представлена цена на автомобили Проблемная область: ценообразование автомобилей Объект наблюдения: автомобили Атрибуты: идентификатор, цена, сбор, производитель, модель, год выпуска, категория, наличие кожаного салона, тип топлива, объём двигателя, пробег, циллиндры, тип коробки передач, колеса, двери, цвет и подушки безопасности. Бизнес-цель: Построение моделей для прогнозирования цен на автомобили на основе их характеристик. Эффект для бизнеса: Оптимизация стратегии продаж и увеличение прибыли. Цель: Разработка модели для прогнозирования цен. Входные данные: Данные о характеристиках автомобилей (год выпуска, тип топлива, пробег и др.). Целевой признак: Цена автомобиля.
df = pd.read_csv("..//static//csv//car_price_prediction.csv")
print(df.columns)
df['Price'] = pd.to_numeric(df['Price'], errors='coerce')
df['Prod. year'] = pd.to_numeric(df['Prod. year'], errors='coerce')
df.dropna(subset=['Price', 'Prod. year'], inplace=True)
avg_price_per_year = df.groupby('Prod. year')['Price'].mean().reset_index()
plt.figure(figsize=(12, 6))
plt.plot(avg_price_per_year['Prod. year'], avg_price_per_year['Price'], marker='o')
plt.title('Средняя цена автомобиля в зависимости от года выпуска', fontsize=14)
plt.xlabel('Год выпуска')
plt.ylabel('Средняя цена ($)')
plt.grid(True)
plt.xticks(avg_price_per_year['Prod. year'][::4])
plt.show()
import numpy as np
# Заменяем "-" на NaN только в числовых столбцах
numeric_columns = ['Price', 'Levy', 'Engine volume', 'Mileage', 'Cylinders', 'Airbags']
df[numeric_columns] = df[numeric_columns].replace("-", np.nan)
# Проверяем пропущенные значения снова
missing_values = df.isnull().sum()
print("Пропущенные значения в данных:\n", missing_values)
# Фильтрация только числовых столбцов для анализа выбросов
numerical_data = df.select_dtypes(include=[np.number])
# 2. Анализ выбросов
Q1 = numerical_data.quantile(0.25)
Q3 = numerical_data.quantile(0.75)
IQR = Q3 - Q1
outliers = ((numerical_data < (Q1 - 1.5 * IQR)) | (numerical_data > (Q3 + 1.5 * IQR))).sum()
print("\nВыбросы в числовых столбцах:\n", outliers)
# 3. Анализ смещения данных
category_counts = df['Manufacturer'].value_counts()
print("\nРаспределение автомобилей по производителям:\n", category_counts)
# 4. Анализ актуальности данных
max_production_year = df['Prod. year'].max()
min_year_from_car = df['Prod. year'].min()
print("\nПоследний год производства в данных:", max_production_year)
print("\nначальный год:", min_year_from_car)
В наборе данных есть пропущенные значения в столбце Levy. Выбросы встречаются с столбцах Price, Prod. year, Cylinders. Набор данных сильно смещён в сторону нескольких производителей, таких как Hyundai, Toyota, и Mercedes-Benz, которые составляют большую часть данных. В то же время, такие бренды, как Lamborghini, Pontiac, Saturn, и Aston Martin, представлены всего одной записью. Последний год выпуска в наборе данных — 2020: Данные устарели на несколько лет. Это может означать, что новые модели автомобилей, выпущенные после 2020 года, не учтены, что снижает актуальность данных для анализа современного рынка автомобилей.
Примеры решения обнаруженных проблем¶
В столбце Levy имеется 5819 пропущенных значений. Заполним пропуски, подставив 0.
df['Levy'] = df['Levy'].fillna(0)
Заменим выбрасы на медиану
for col in ['Price', 'Prod. year', 'Cylinders']:
Q1 = df[col].quantile(0.25) # 1-й квартиль
Q3 = df[col].quantile(0.75) # 3-й квартиль
IQR = Q3 - Q1 # Интерквартильный размах
median = df[col].median() # Медиана
# Определение выбросов
condition = (df[col] < (Q1 - 1.5 * IQR)) | (df[col] > (Q3 + 1.5 * IQR))
# Замена выбросов на медиану
df[col] = np.where(condition, median, df[col])
Если нужно использовать для анализа машины определенных лет выпуска, можем отфильтровать данные следующим образом:
df = df[df['Prod. year'] >= 2015]
Оценка качества данных¶
Для каждой категориальной переменной, такой как Manufacturer, Model, Category, можно подсчитать количество уникальных значений. Это даст представление о разнообразии и информативности данных.
unique_counts = df.nunique()
print(unique_counts)
Мы видим здесь 65 брендов машин и 1590 различных моделей, что говорит а разнообразии данных.
Проверим на соответствие реальным данным
plt.figure(figsize=(10, 5))
sns.boxplot(x='Category', y='Price', data=df)
plt.title('Цены по категориям автомобилей')
plt.xlabel('Категория')
plt.ylabel('Цена')
plt.xticks(rotation=45)
plt.show()
данная диаграмма была получина до устранения выбрасов.
plt.figure(figsize=(10, 5))
sns.boxplot(x='Category', y='Price', data=df)
plt.title('Цены по категориям автомобилей')
plt.xlabel('Категория')
plt.ylabel('Цена')
plt.xticks(rotation=45)
plt.show()
После устранения выбрасов, диаграмма выглядит лучше, хотя здесь все равно присутствуют очень маленькие значения, что не соответсвуем реальным ценам на машины. Из этого можем сделать вывод, что цены в наборе данных не особо соответствуют реальности.
Разбиение набора данных на обучающую, контрольную и тестовую выборки
# Загрузка данных
new1 = pd.read_csv("..//static//csv//car_price_prediction.csv")
# Разбиение на обучающую и временную выборки
train_data, temp_data = train_test_split(new1, test_size=0.3, random_state=42)
# Разбиение временной выборки на контрольную и тестовую
val_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42)
print("Размер обучающей выборки:", len(train_data))
print("Размер контрольной выборки:", len(val_data))
print("Размер тестовой выборки:", len(test_data))
# Определяем целевую переменную и признаки
X = train_data.drop(columns=['Manufacturer']) # Признаки
y = train_data['Manufacturer'] # Целевая переменная
# Функция для визуализации распределения
def plot_class_distribution(data, title):
data['Manufacturer'].value_counts().plot(kind='bar', title=title)
plt.xlabel('Manufacturer')
plt.ylabel('Count')
plt.show()
# Визуализация распределения классов до оверсэмплинга
plot_class_distribution(train_data, 'Распределение классов в обучающей выборке (до оверсэмплинга)')
Выполним овер- и андер- слемпинг.
# Применение оверсэмплинга
ros = RandomOverSampler(random_state=42)
X_resampled, y_resampled = ros.fit_resample(X, y)
# Создание нового DataFrame для оверсэмплинга
train_resampled_over = pd.DataFrame(X_resampled, columns=X.columns)
train_resampled_over['Manufacturer'] = y_resampled
# Визуализация распределения классов после оверсэмплинга
plot_class_distribution(train_resampled_over, 'Распределение классов в обучающей выборке (после оверсэмплинга)')
# Применение андерсэмплинга
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X, y)
# Создание нового DataFrame для андерсэмплинга
train_resampled_under = pd.DataFrame(X_resampled, columns=X.columns)
train_resampled_under['Manufacturer'] = y_resampled
# Визуализация распределения классов после андерсэмплинга
plot_class_distribution(train_resampled_under, 'Распределение классов в обучающей выборке (после андерсэмплинга)')