Загрузка данных


import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

sns.set_theme(style='whitegrid', font='DejaVu Sans')

df = pd.read_csv('data.csv')
df['Metro station'] = df['Metro station'].str.strip()

# Названия и смысл всех столбцов
columns = {
    'Price': 'цена квартиры, руб.',
    'Apartment type': 'вторичное жильё или новостройка',
    'Metro station': 'ближайшая станция метро',
    'Minutes to metro': 'минут пешком до метро',
    'Region': 'Москва или Московская область',
    'Number of rooms': 'количество комнат',
    'Area': 'общая площадь, м²',
    'Living area': 'жилая площадь, м²',
    'Kitchen area': 'площадь кухни, м²',
    'Floor': 'этаж квартиры',
    'Number of floors': 'количество этажей в доме',
    'Renovation': 'тип ремонта'
}

print('Размер датасета:', df.shape)
print('\nСтолбцы:')
for name in df.columns:
    print(name, '—', columns[name])

print('\nОбщая информация:')
df.info()

print('\nЧисловые показатели:')
print(df.describe().round(2))

print('\nУникальные значения текстовых столбцов:')
for name in ['Apartment type', 'Region', 'Renovation']:
    print(name, ':', df[name].unique())
print('Количество станций метро:', df['Metro station'].nunique())

# Убираем крайние значения цены и площади, которые мешают читать графики
work = df[
    df['Area'].between(15, 200) &
    df['Price'].between(2_000_000, 100_000_000)
].copy()

work['Price_mln'] = work['Price'] / 1_000_000
work['Price_per_m2'] = work['Price'] / work['Area'] / 1000

print('\nКвартир после отбора:', len(work))

# Фильтрация: двухкомнатные квартиры на вторичном рынке Москвы
selected = work[
    (work['Region'] == 'Moscow') &
    (work['Number of rooms'] == 2) &
    (work['Apartment type'] == 'Secondary')
]
print('\nПример отфильтрованных квартир:')
print(selected[['Price', 'Area', 'Metro station', 'Renovation']].head(10))

# Группировка: количество, минимум, максимум и среднее
by_region = work.groupby(['Region', 'Apartment type']).agg(
    count=('Price', 'size'),
    min_price=('Price_mln', 'min'),
    max_price=('Price_mln', 'max'),
    mean_price=('Price_mln', 'mean'),
    mean_price_m2=('Price_per_m2', 'mean')
).round(2)

print('\nЦены по регионам и типам жилья:')
print(by_region)

# Консолидация: объединяем площадь в диапазоны
work['Area_group'] = pd.cut(
    work['Area'],
    bins=[15, 30, 45, 60, 80, 120, 200],
    include_lowest=True
)

by_area = work.groupby('Area_group', observed=True)['Price_per_m2'].agg(
    ['count', 'min', 'max', 'mean']
).round(2)

print('\nЦена за м² по диапазонам площади, тыс. руб.:')
print(by_area)

print('\nДиапазоны изменения числовых данных:')
print(work[['Price_mln', 'Area', 'Minutes to metro', 'Price_per_m2']]
      .agg(['min', 'max']))

# Преобразуем значения Region в отдельные столбцы
wide = (
    work.groupby(['Area_group', 'Region'], observed=True)['Price_per_m2']
    .mean()
    .unstack('Region')
)

print('\nТаблица с регионами в отдельных столбцах:')
print(wide.round(2))

# 1. Scatter: сравнение двух числовых столбцов
plt.figure(figsize=(8, 5))
sns.scatterplot(
    data=work.sample(n=1500, random_state=10),
    x='Area', y='Price_mln', hue='Region', alpha=0.5
)
plt.title('Площадь и цена квартиры')
plt.xlabel('Площадь, м²')
plt.ylabel('Цена, млн руб.')
plt.tight_layout()
plt.show()

# 2. Pair plot: попарное сравнение числовых столбцов
sns.pairplot(
    work.sample(n=400, random_state=10),
    vars=['Price_mln', 'Area', 'Minutes to metro'],
    hue='Region'
)
plt.show()

# 3. Bar: сравнение нескольких категорий
plt.figure(figsize=(8, 5))
sns.barplot(
    data=work, x='Region', y='Price_per_m2',
    hue='Apartment type', errorbar=None
)
plt.title('Средняя цена за м² по региону и типу жилья')
plt.xlabel('Регион')
plt.ylabel('Цена за м², тыс. руб.')
plt.tight_layout()
plt.show()

# 4. Круговая диаграмма
plt.figure(figsize=(6, 6))
work['Renovation'].value_counts().plot.pie(autopct='%1.1f%%')
plt.title('Доли квартир по типу ремонта')
plt.ylabel('')
plt.tight_layout()
plt.show()

# 5. Цветовая карта корреляций
plt.figure(figsize=(7, 5))
corr = work[
    ['Price_mln', 'Area', 'Number of rooms', 'Minutes to metro', 'Floor']
].corr()
sns.heatmap(corr, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Корреляция числовых показателей')
plt.tight_layout()
plt.show()

# 6. Линейный график из таблицы, где регионы стали столбцами
wide.plot(marker='o', figsize=(9, 5))
plt.title('Средняя цена за м² по диапазонам площади')
plt.xlabel('Площадь, м²')
plt.ylabel('Цена за м², тыс. руб.')
plt.xticks(rotation=30)
plt.tight_layout()
plt.show()