520 KiB
- Продажи домов
- Данные о населении
- Набор данных для анализа и прогнозирования сердечного приступа
Продажа домов
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
df = pd.read_csv("..//static//csv//House.csv", index_col="id")
print(df.columns, "\n")
Столбцы для русских:
id: Идентификатор объекта
date: Дата продажи
price: Цена недвижимости
bedrooms: Количество спален
bathrooms: Количество ванных комнат
sqft_living: Жилая площадь
sqft_lot: Площадь участка
floors: Количество этажей
waterfront: Признак наличия вида на водоем
view: Оценка вида
condition: Состояние дома
grade: Оценка конструкции
sqft_above: Площадь надземных помещений
sqft_basement: Площадь подвала
yr_built: Год постройки
yr_renovated: Год последнего ремонта
zipcode: Почтовый индекс
lat: Широта
long: Долгота
sqft_living15: Жилая площадь соседних домов
sqft_lot15: Площадь участка соседних домов
Проблемная область: Прогнозирование стоимости недвижимости в зависимости от характеристик дома.
print(df.info, "\n")
Объектом наблюдения является - Недвижимость
Атрибуты - содержит набор информации о продаже дома, такие как:
цену продажи, дата продажи, количество спален, ванных комнат, общую площадь дома, площадь участка, местоположение.
plt.figure(figsize=(10, 6))
plt.scatter(df['sqft_living'], df['price'], c=df['price'], alpha=0.6)
plt.colorbar(label='Price')
plt.title("Номер 1")
plt.ylabel("Price")
plt.xlabel("Living Area")
plt.grid(visible='true')
plt.show()
year_condition = df.groupby('yr_built')['condition'].mean().reset_index()
plt.figure(figsize=(12, 6))
plt.plot(year_condition['yr_built'], year_condition['condition'], marker='.')
plt.title("Номер 2")
plt.xlabel("Year Built")
plt.ylabel("Condition")
plt.show()
Связь между объектами есть. Цена связана почти со всеми характиристиками дома.
Например на графике номер один показана зависимоость между ценой и размером дома.
А на графике номер 2 показа зависимость состояния домов с годами.
Примеры бизнес целей
- Прогнозирование стоимости недвижимости на основе характиристик дома.
- Наблюдение за изменениями характиристик дома с годами.
Эффект для бизнеса: Оценка и оптимизация цен, Оценка и планирование затрат, выявление тенденции на рынке, стратегия планирования.
Цели технического проекта
- Для первой цели:
- Для второй цели:
Код ниже нужен для определения проблем данных
max_value = df.max(axis=0)
columns_with_zero = df.columns[(df == 0).any()]
numeric_data = df.select_dtypes(include='number')
shum = numeric_data.var()
low_dispers = 0.1
low_var_columns = shum[shum < low_dispers]
year = df['yr_built']
print(max_value, "\n")
print(columns_with_zero, "\n")
print("Признаки с низкой дисперсией:\n", low_var_columns, "\n")
print(year)
Из полученных данных выяснилось:
Примеры решения проблем для набора данных
Оценка качества данных
1. Информативность. Набор данных предоставляет достаточную информацию для анализа цен на недвижимость. 2. Степень покрытия. Набор данных затрагивает только один райно, не включая информацию о других райнов. 3. Соответствие реальным данным. Данные вполне кажутся реальными, не считая некоторых редких выбросов. 4. Согласованность меток. Метки состояние и оценка вида, имеют четкие значения.Разбиение данных на обучающую, контрольную и тестовую выборки
df_numeric = df.select_dtypes(include='number')
x = df_numeric.drop(['price'], axis=1)
y = df_numeric['price']
x_train, x_temp, y_train, y_temp = train_test_split(x, y, test_size=0.3, random_state=14)
x_val, x_test, y_val, y_test = train_test_split(x_temp, y_temp, test_size=0.5, random_state=14)
print(f"Исходный размер строк: {df_numeric.shape[0]} строк")
print(f"Размер обучающей выборки: {x_train.shape[0]} строк")
print(f"Размер валидационной выборки: {x_val.shape[0]} строк")
print(f"Размер тестовой выборки: {x_test.shape[0]} строк")
import seaborn as sns
df['price_log'] = np.log(df['price'])
X = df.drop(['price', 'price_log'], axis=1)
y = df['price_log']
X = X.select_dtypes(include='number')
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.3, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
def plot_distribution(data, title):
"""Построение гистограммы распределения целевого признака"""
plt.figure(figsize=(10, 6))
sns.histplot(data, kde=True, bins=30, color='skyblue')
plt.title(title)
plt.xlabel('Logarithm of Price')
plt.ylabel('Count')
plt.grid(True)
plt.show()
plot_distribution(y_train, 'Распределение логарифма цены в обучающей выборке')
plot_distribution(y_val, 'Распределение логарифма цены в валидационной выборке')
plot_distribution(y_test, 'Распределение логарифма цены в тестовой выборке')
def get_statistics(df, name):
print(f"Статистические показатели для {name} выборки:")
print(f"Среднее значение: {df.mean():.2f}")
print(f"Стандартное отклонение: {df.std():.2f}")
print(f"Минимальное значение: {df.min():.2f}")
print(f"Максимальное значение: {df.max():.2f}")
print(f"Количество наблюдений: {df.count()}\n")
get_statistics(y_train, "обучающей")
get_statistics(y_val, "валидационной")
get_statistics(y_test, "тестовой")
Oversampling и undersampling
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
if 'date' in df.columns:
df['year'] = pd.to_datetime(df['date'], errors='coerce').dt.year
df = df.drop(['date'], axis=1)
df['price_log'] = np.log(df['price'])
df['price_category'] = pd.qcut(df['price_log'], q=5, labels=[0, 1, 2, 3, 4])
X = df.drop(['price', 'price_log', 'price_category'], axis=1)
y = df['price_category']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
print("Распределение классов после SMOTE (oversampling):")
print(pd.Series(y_train_smote).value_counts())
undersampler = RandomUnderSampler(random_state=42)
X_train_under, y_train_under = undersampler.fit_resample(X_train, y_train)
print("Распределение классов после RandomUnderSampler (undersampling):")
print(pd.Series(y_train_under).value_counts())
Оценка сбалансированности выборок
Оценка необходимости аугментации данных
def check_augmentation_need(data, name):
"""Проверка необходимости аугментации данных"""
quantiles = data.quantile([0.25, 0.5, 0.75])
mean = data.mean()
std = data.std()
print(f"Проверка необходимости аугментации для {name} выборки:")
print(f"Среднее значение: {mean:.2f}, Стандартное отклонение: {std:.2f}")
print(f"25-й квантиль: {quantiles[0.25]:.2f}")
print(f"50-й квантиль (медиана): {quantiles[0.5]:.2f}")
print(f"75-й квантиль: {quantiles[0.75]:.2f}")
if std > mean * 0.5:
print(f"Выборка {name} несбалансирована, рекомендуется аугментация.\n")
else:
print(f"Выборка {name} сбалансирована, аугментация не требуется.\n")
check_augmentation_need(y_train, "обучающей")
check_augmentation_need(y_val, "валидационной")
check_augmentation_need(y_test, "тестовой")
Поскольку все выборки демонстрируют одинаковое распределение целевого признака и сбалансированное распределение значений, применение методов аугментации не требуется.
if 'condition' in df.columns:
X_train, X_temp, y_train, y_temp = train_test_split(df.drop(['price'], axis=1), df['condition'], test_size=0.3, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
def analyze_condition_distribution(data, name):
"""Проверка и визуализация распределения признака 'condition'"""
condition_counts = data.value_counts()
print(f"Распределение 'condition' в {name} выборке:\n", condition_counts)
plt.figure(figsize=(8, 6))
sns.barplot(x=condition_counts.index, y=condition_counts.values, palette='viridis')
plt.title(f"Распределение признака 'condition' в {name} выборке")
plt.xlabel('Condition')
plt.ylabel('Count')
plt.grid(True)
plt.show()
analyze_condition_distribution(y_train, 'обучающей')
analyze_condition_distribution(y_val, 'валидационной')
analyze_condition_distribution(y_test, 'тестовой')
def check_condition_augmentation(data, name):
print(f"Проверка необходимости аугментации для признака 'condition' в {name} выборке:")
min_count = data.value_counts().min()
max_count = data.value_counts().max()
print(f"Минимальное количество наблюдений в классе: {min_count}")
print(f"Максимальное количество наблюдений в классе: {max_count}")
if max_count > min_count * 1.5:
print(f"Выборка '{name}' несбалансирована, рекомендуется аугментация.\n")
else:
print(f"Выборка '{name}' сбалансирована, аугментация не требуется.\n")
check_condition_augmentation(y_train, 'обучающей')
check_condition_augmentation(y_val, 'валидационной')
check_condition_augmentation(y_test, 'тестовой')
else:
print("Признак 'condition' отсутствует в данных.")
smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
print("Распределение классов после SMOTE (oversampling):")
print(pd.Series(y_train_smote).value_counts())
undersampler = RandomUnderSampler(random_state=42)
X_train_under, y_train_under = undersampler.fit_resample(X_train, y_train)
print("Распределение классов после RandomUnderSampler (undersampling):")
print(pd.Series(y_train_under).value_counts())
В этом исследование данные не сбалансированы, поэтому требуется аугментация.
Данные о населении
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
df2 = pd.read_csv("..//static//csv//WorldPopulation.csv", index_col="no")
print(df2.head(), "\n")
print(*list(df2.columns), sep='\n')
Объектом наблюдения является страны и информация о их наслении.
Атрибуты объекта: Страна, Население, Годовое изменение, NetChange, Плотность, Площадь суши, Мигранты, Fert.Rate, Средний возраст, UrbanPop%, Доля в мире;
Связь между объектами: имеется связь между атрибутами, например между Коэффициент фертильности и Плотностю населения.
df2['Fert. Rate'] = pd.to_numeric(df2['Fert. Rate'], errors='coerce')
df2['Fert. Rate'] = pd.to_numeric(df2['Fert. Rate'], errors='coerce')
df_clean = df2.dropna(subset=['Fert. Rate', 'Density (P/Km²)'])
## correlation = df_clean[['Density (P/Km²)', 'Fert. Rate']].corr().iloc[0, 1] ## использовать только один раз потом удалить
df_clean['Density (P/Km²)'] = pd.cut(df2['Density (P/Km²)'], bins=range(0, 1000, 100))
plt.figure(figsize=(10, 6))
sns.boxplot(data=df_clean, x='Density (P/Km²)', y='Fert. Rate')
plt.title('Распределение уровня рождаемости по плотности населения')
plt.xlabel('Плотность (чел./км²)')
plt.ylabel('Уровень рождаемости')
plt.xticks(rotation=45)
plt.show()
plt.show()
df2['Med. Age'] = pd.to_numeric(df2['Med. Age'], errors='coerce')
df2['Med. Age'] = pd.to_numeric(df2['Med. Age'], errors='coerce')
df_clean = df2.dropna(subset=['Fert. Rate', 'Density (P/Km²)'])
## correlation = df_clean[['Density (P/Km²)', 'Fert. Rate']].corr().iloc[0, 1] ## использовать только один раз потом удалить
df_clean['Density (P/Km²)'] = pd.cut(df2['Density (P/Km²)'], bins=range(0, 1000, 100))
plt.figure(figsize=(10, 6))
sns.boxplot(data=df_clean, x='Density (P/Km²)', y='Fert. Rate')
plt.title('Распределение уровня рождаемости по плотности населения')
plt.xlabel('Плотность (чел./км²)')
plt.ylabel('Уровень рождаемости')
plt.xticks(rotation=45)
plt.show()
plt.show()