286 KiB
Выгрузка в датафрейм первый набор (игры в Steam)¶
https://www.kaggle.com/datasets/wajihulhassan369/steam-games-dataset. Набор представляет собой данные об экшенах, доступных в Steam. Эта информация полезна для изучения игровых паттернов, моделирования цен и исследования корреляции между игровыми тегами и методами ценообразования. Этот набор позволяет провести предварительный анализ данных, построить модели машинного обучения или исследовать игровую индустрию. В наборе пресдтавлена дата, различные теги, рейтинг отзывов. Так можно понять, какие теги популярнее, что в играх людям нравится больше, изменилось ли качество игр со временем и т.д. Для бизнеса такой набор данных может быть полезен для прогнозирования, в разработку каки игр целесообразнее вкладываться. Так компания не потеряет деньги. Пример цели: Разработка игры на пк в нужную фазу рынка Входные данные: год выпуска, сумма продаж Целевой признак: продаваемость игр в текущей фазе рынка в сравнении с предыдущими.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv(".//static//csv//steam_cleaned.csv")
print(df.columns)
# Преобразуем дату выпуска в формат datetime
df['Release_date'] = pd.to_datetime(df['Release_date'])
# Визуализация данных
plt.figure(figsize=(10, 6))
plt.scatter(df['Release_date'], df['Review_no'])
plt.xlabel('Release Date')
plt.ylabel('Review Number')
plt.title('Scatter Plot of Review Number vs Release Date')
plt.show()
При проверке на шум можно заметить выброс в 2014 году. количество обзоров там запредельное.
Все выбросы удалены путём определения порогов квантилями. Зашумленность не очень высокая. Покрытие данных высокое и подошло бы для поставленной задачи по актуальности.
# Преобразуем дату выпуска в формат datetime
df['Release_date'] = pd.to_datetime(df['Release_date'])
# Статистический анализ для определения выбросов
Q1 = df['Review_no'].quantile(0.25)
Q3 = df['Review_no'].quantile(0.75)
IQR = Q3 - Q1
# Определение порога для выбросов
threshold = 1.5 * IQR
outliers = (df['Review_no'] < (Q1 - threshold)) | (df['Review_no'] > (Q3 + threshold))
# Вывод выбросов
print("Выбросы:")
print(df[outliers])
# Обработка выбросов
# В данном случае мы заменим выбросы на медианное значение
median_review_no = df['Review_no'].median()
df.loc[outliers, 'Review_no'] = median_review_no
# Визуализация данных после обработки
plt.figure(figsize=(10, 6))
plt.scatter(df['Release_date'], df['Review_no'])
plt.xlabel('Release Date')
plt.ylabel('Review Number')
plt.title('Scatter Plot of Review Number vs Release Date (After Handling Outliers)')
plt.show()
Очистим от строк с пустыми значениями наш датасет
# Удаление строк с пропущенными значениями
df_dropna = df.dropna()
# Вывод количества удаленных строк
num_deleted_rows = len(df) - len(df_dropna)
print(f"\nКоличество удаленных строк: {num_deleted_rows}")
print("\nDataFrame после удаления строк с пропущенными значениями:")
print(df_dropna)
Теперь создадим выборки.
import pandas as pd
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv(".//static//csv//steam_cleaned.csv")
train_df, temp_df = train_test_split(df, test_size=0.4, random_state=42)
# Разделение остатка на контрольную и тестовую выборки
val_df, test_df = train_test_split(temp_df, test_size=0.5, random_state=42)
# Проверка размеров выборок
print("Размер обучающей выборки:", len(train_df))
print("Размер контрольной выборки:", len(val_df))
print("Размер тестовой выборки:", len(test_df))
# Сохранение выборок в файлы
train_df.to_csv(".//static//csv//train_data.csv", index=False)
val_df.to_csv(".//static//csv//val_data.csv", index=False)
test_df.to_csv(".//static//csv//test_data.csv", index=False)
Проанализируем сбалансированность выборок
train_df = pd.read_csv(".//static//csv//train_data.csv")
val_df = pd.read_csv(".//static//csv//val_data.csv")
test_df = pd.read_csv(".//static//csv//test_data.csv")
# Оценка сбалансированности
def check_balance(df, name):
counts = df['Review_type'].value_counts()
print(f"Распределение Review_type в {name}:")
print(counts)
print(f"Процент положительных отзывов: {counts['Mostly Positive'] / len(df) * 100:.2f}%")
print(f"Процент отрицательных отзывов: {counts['Overwhelmingly Positive'] / len(df) * 100:.2f}%")
print()
# Определение необходимости аугментации данных
def need_augmentation(df):
counts = df['Review_type'].value_counts()
ratio = counts['Mostly Positive'] / counts['Overwhelmingly Positive']
if ratio > 1.5 or ratio < 0.67:
print("Необходима аугментация данных для балансировки классов.")
else:
print("Аугментация данных не требуется.")
check_balance(train_df, "обучающей выборке")
check_balance(val_df, "контрольной выборке")
check_balance(test_df, "тестовой выборке")
need_augmentation(train_df)
need_augmentation(val_df)
need_augmentation(test_df)
По результатам анализа требуется приращение, соотношения отзывов вне допустимого диапазона
import pandas as pd
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
from sklearn.preprocessing import LabelEncoder
# Загрузка данных
train_df = pd.read_csv(".//static//csv//train_data.csv")
val_df = pd.read_csv(".//static//csv//val_data.csv")
test_df = pd.read_csv(".//static//csv//test_data.csv")
# Преобразование категориальных признаков в числовые
def encode(df):
label_encoders = {}
for column in df.select_dtypes(include=['object']).columns:
if column != 'Review_type': # Пропускаем целевую переменную
le = LabelEncoder()
df[column] = le.fit_transform(df[column])
label_encoders[column] = le
return label_encoders
# Преобразование целевой переменной в числовые значения
def encode_target(df):
le = LabelEncoder()
df['Review_type'] = le.fit_transform(df['Review_type'])
return le
# Применение кодирования
label_encoders = encode(train_df)
encode(val_df)
encode(test_df)
# Кодирование целевой переменной
le_target = encode_target(train_df)
encode_target(val_df)
encode_target(test_df)
# Проверка типов данных
def check_data_types(df):
for column in df.columns:
if df[column].dtype == 'object':
print(f"Столбец '{column}' содержит строковые данные.")
check_data_types(train_df)
check_data_types(val_df)
check_data_types(test_df)
# Функция для выполнения oversampling
def oversample(df):
if 'Review_type' not in df.columns:
print("Столбец 'Review_type' отсутствует.")
return df
X = df.drop('Review_type', axis=1)
y = df['Review_type']
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
# Функция для выполнения undersampling
def undersample(df):
if 'Review_type' not in df.columns:
print("Столбец 'Review_type' отсутствует.")
return df
X = df.drop('Review_type', axis=1)
y = df['Review_type']
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
# Применение oversampling и undersampling к каждой выборке
train_df_oversampled = oversample(train_df)
val_df_oversampled = oversample(val_df)
test_df_oversampled = oversample(test_df)
train_df_undersampled = undersample(train_df)
val_df_undersampled = undersample(val_df)
test_df_undersampled = undersample(test_df)
# Обратное преобразование целевой переменной в строковые метки
def decode_target(df, le_target):
df['Review_type'] = le_target.inverse_transform(df['Review_type'])
decode_target(train_df_oversampled, le_target)
decode_target(val_df_oversampled, le_target)
decode_target(test_df_oversampled, le_target)
decode_target(train_df_undersampled, le_target)
decode_target(val_df_undersampled, le_target)
decode_target(test_df_undersampled, le_target)
# Проверка результатов
def check_balance(df, name):
if 'Review_type' not in df.columns:
print(f"Столбец 'Review_type' отсутствует в {name}.")
return
counts = df['Review_type'].value_counts()
print(f"Распределение Review_type в {name}:")
print(counts)
if 'Positive' in counts and 'Negative' in counts:
print(f"Процент положительных отзывов: {counts['Positive'] / len(df) * 100:.2f}%")
print(f"Процент отрицательных отзывов: {counts['Negative'] / len(df) * 100:.2f}%")
else:
print("Отсутствуют один или оба класса (Positive/Negative).")
print()
# Проверка сбалансированности после oversampling
print("Оверсэмплинг:")
check_balance(train_df_oversampled, "обучающей выборке")
check_balance(val_df_oversampled, "контрольной выборке")
check_balance(test_df_oversampled, "тестовой выборке")
# Проверка сбалансированности после undersampling
print("Андерсэмплинг:")
check_balance(train_df_undersampled, "обучающей выборке")
check_balance(val_df_undersampled, "контрольной выборке")
check_balance(test_df_undersampled, "тестовой выборке")
14,400 Classic Rock Tracks (with Spotify Data)¶
https://www.kaggle.com/datasets/thebumpkin/14400-classic-rock-tracks-with-spotify-data Этот набор данных, содержащий 1200 уникальных альбомов и 14 400 треков, представляет собой не просто коллекцию — это хроника эволюции классического рока. Каждый трек тщательно каталогизирован с 18 столбцами данных, включая ключевые метаданные, такие как название трека, исполнитель, альбом и год выпуска, наряду с функциями Spotify audio, которые позволяют получить представление о звуковом ландшафте этих неподвластных времени мелодий. Бизнес-цель может заключаться в улучшении стратегии маркетинга и продвижения музыкальных треков. Предположим как этот набор может быть полезен для бизнеса: Персонализированные рекомендации: Создание алгоритмов, которые будут рекомендовать пользователям музыку на основе их предпочтений. Цель технического проекта: Разработать и внедрить систему рекомендаций, которая будет предсказывать и рекомендовать пользователям музыкальные треки на основе их предпочтений и поведения. Входные данные: Данные о пользователях: Идентификатор пользователя, история прослушиваний, оценки треков, время прослушивания, частота прослушивания. Данные о треках: Атрибуты треков (название, исполнитель, альбом, год, длительность, танцевальность, энергичность, акустичность и т.д.). Данные о взаимодействии: Время и частота взаимодействия пользователя с определенными треками. Целевой признак: Рекомендации: Булева переменная, указывающая, должен ли конкретный трек быть рекомендован пользователю (1 - рекомендуется, 0 - не рекомендуется).
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv(".//static//csv//UltimateClassicRock.csv")
print(df.columns)
Анализируем датафрейм при помощи "ящика с усами". Естьсмещение в сторону меньших значений, это можно исправить при помощи oversampling и undersampling.
import matplotlib.pyplot as plt
import seaborn as sns
# 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()
Разбиение набора данных на обучающую, контрольную и тестовую выборки
from sklearn.model_selection import train_test_split
# Разделение на обучающую и тестовую выборки
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, "тестовой выборке")
Выполним овер- и андер- слемпинг.
from imblearn.over_sampling import RandomOverSampler
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")
from imblearn.under_sampling import RandomUnderSampler
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")
Police Shootings in the United States: 2015-2024¶
В этом наборе данных, составленном The Washington Post, регистрируется каждый человек, застреленный дежурным полицейским в Соединенных Штатах с 2015 по 2024 год. Он решает проблему занижения органами власти статистики реальных инцедентов. Это может быть использовано в журналисткой работе, например для прогнозирования или выявления закономерностей преступлений. Цель технического проекта установить закономерность в убийствах полицейскими определённых групп граждан. Входные данные: возраст, пол, штат, вооружённость. Целевой признак: общий портрет убитого гражданина.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv(".//static//csv//2024-07-23-washington-post-police-shootings-export.csv")
print(df.columns)
При помощи ящика с усами и колонки возраста проверим набор на баланс. Он достаточно сбалансирован.
import matplotlib.pyplot as plt
import seaborn as sns
# Box plot для столбца 'age'
plt.figure(figsize=(10, 6))
sns.boxplot(x=df['age'])
plt.title('Box Plot для age')
plt.xlabel('Age')
plt.show()
Теперь проверим на шум, здесь тоже особо проблем нет, однако смущает сочетание white и black, вероятно это мулаты.
import matplotlib.pyplot as plt
import seaborn as sns
# Scatter plot для столбцов 'age' и 'race'
plt.figure(figsize=(10, 6))
sns.scatterplot(x='age', y='race', data=df)
plt.title('Scatter Plot для age и race')
plt.xlabel('Age')
plt.ylabel('Race')
plt.show()
Удаление строк с пустыми значениями
df_cleaned = df.dropna()
Разбиение набора данных на обучающую, контрольную и тестовую выборки
from sklearn.model_selection import train_test_split
# Разделение на обучающую и тестовую выборки
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))
Применение методов приращения данных (аугментации)
from imblearn.over_sampling import RandomOverSampler
def check_balance(df, name):
counts = df['race'].value_counts()
print(f"Распределение reace в {name}:")
print(counts)
print()
def oversample(df):
X = df.drop('race', axis=1)
y = df['race']
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('race', axis=1)
y = df['race']
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")