Спасибо за работу и успехов в следующих проектах!)
Меня зовут Михаленко Дмитрий, и я буду проверять твой проект. Предлагаю общаться на «ты» :) Но если это не удобно - дай знать, и мы перейдем на "вы".
Моя основная цель — не указать на совершенные тобою ошибки, а поделиться своим опытом и помочь тебе стать аналитиком данных. Ты уже проделал большую работу над проектом, но давай сделаем его еще лучше. Ниже ты найдешь мои комментарии - пожалуйста, не перемещай, не изменяй и не удаляй их. Увидев у тебя ошибку, в первый раз я лишь укажу на ее наличие и дам тебе возможность самому найти и исправить ее. На реальной работе твой начальник будет поступать так же, а я пытаюсь подготовить тебя именно к работе аналитиком. Но если ты пока не справишься с такой задачей - при следующей проверке я дам более точную подсказку. Я буду использовать цветовую разметку:
Давай работать над проектом в диалоге: если ты что-то меняешь в проекте или отвечаешь на мои комментарии — пиши об этом. Мне будет легче отследить изменения, если ты выделишь свои комментарии:
Всё это поможет выполнить повторную проверку твоего проекта оперативнее.
Исследование объявлений о продаже квартир¶
В вашем распоряжении данные сервиса Яндекс.Недвижимость — архив объявлений о продаже квартир в Санкт-Петербурге и соседних населённых пунктов за несколько лет. Нужно научиться определять рыночную стоимость объектов недвижимости. Ваша задача — установить параметры. Это позволит построить автоматизированную систему: она отследит аномалии и мошенническую деятельность.
По каждой квартире на продажу доступны два вида данных. Первые вписаны пользователем, вторые — получены автоматически на основе картографических данных. Например, расстояние до центра, аэропорта, ближайшего парка и водоёма.
Откройте файл с данными и изучите общую информацию.¶
1)Открыли файл с данными, поместили их ДФ.
2)Методом .info() получили сводную информацию по ДФ: пропуски в значениях,типы данныхи сами данные в каких колонках находяться
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.read_csv('/datasets/real_estate_data.csv',sep='\t')
data.info()
print('\n' * 3)
print(data.head())
data.hist(figsize=(15,15), bins=50)
<class 'pandas.core.frame.DataFrame'> RangeIndex: 23699 entries, 0 to 23698 Data columns (total 22 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 total_images 23699 non-null int64 1 last_price 23699 non-null float64 2 total_area 23699 non-null float64 3 first_day_exposition 23699 non-null object 4 rooms 23699 non-null int64 5 ceiling_height 14504 non-null float64 6 floors_total 23613 non-null float64 7 living_area 21796 non-null float64 8 floor 23699 non-null int64 9 is_apartment 2775 non-null object 10 studio 23699 non-null bool 11 open_plan 23699 non-null bool 12 kitchen_area 21421 non-null float64 13 balcony 12180 non-null float64 14 locality_name 23650 non-null object 15 airports_nearest 18157 non-null float64 16 cityCenters_nearest 18180 non-null float64 17 parks_around3000 18181 non-null float64 18 parks_nearest 8079 non-null float64 19 ponds_around3000 18181 non-null float64 20 ponds_nearest 9110 non-null float64 21 days_exposition 20518 non-null float64 dtypes: bool(2), float64(14), int64(3), object(3) memory usage: 3.7+ MB total_images last_price total_area first_day_exposition rooms \ 0 20 13000000.0 108.0 2019-03-07T00:00:00 3 1 7 3350000.0 40.4 2018-12-04T00:00:00 1 2 10 5196000.0 56.0 2015-08-20T00:00:00 2 3 0 64900000.0 159.0 2015-07-24T00:00:00 3 4 2 10000000.0 100.0 2018-06-19T00:00:00 2 ceiling_height floors_total living_area floor is_apartment ... \ 0 2.70 16.0 51.0 8 NaN ... 1 NaN 11.0 18.6 1 NaN ... 2 NaN 5.0 34.3 4 NaN ... 3 NaN 14.0 NaN 9 NaN ... 4 3.03 14.0 32.0 13 NaN ... kitchen_area balcony locality_name airports_nearest \ 0 25.0 NaN Санкт-Петербург 18863.0 1 11.0 2.0 посёлок Шушары 12817.0 2 8.3 0.0 Санкт-Петербург 21741.0 3 NaN 0.0 Санкт-Петербург 28098.0 4 41.0 NaN Санкт-Петербург 31856.0 cityCenters_nearest parks_around3000 parks_nearest ponds_around3000 \ 0 16028.0 1.0 482.0 2.0 1 18603.0 0.0 NaN 0.0 2 13933.0 1.0 90.0 2.0 3 6800.0 2.0 84.0 3.0 4 8098.0 2.0 112.0 1.0 ponds_nearest days_exposition 0 755.0 NaN 1 NaN 81.0 2 574.0 558.0 3 234.0 424.0 4 48.0 121.0 [5 rows x 22 columns]
array([[<AxesSubplot:title={'center':'total_images'}>,
<AxesSubplot:title={'center':'last_price'}>,
<AxesSubplot:title={'center':'total_area'}>,
<AxesSubplot:title={'center':'rooms'}>],
[<AxesSubplot:title={'center':'ceiling_height'}>,
<AxesSubplot:title={'center':'floors_total'}>,
<AxesSubplot:title={'center':'living_area'}>,
<AxesSubplot:title={'center':'floor'}>],
[<AxesSubplot:title={'center':'kitchen_area'}>,
<AxesSubplot:title={'center':'balcony'}>,
<AxesSubplot:title={'center':'airports_nearest'}>,
<AxesSubplot:title={'center':'cityCenters_nearest'}>],
[<AxesSubplot:title={'center':'parks_around3000'}>,
<AxesSubplot:title={'center':'parks_nearest'}>,
<AxesSubplot:title={'center':'ponds_around3000'}>,
<AxesSubplot:title={'center':'ponds_nearest'}>],
[<AxesSubplot:title={'center':'days_exposition'}>, <AxesSubplot:>,
<AxesSubplot:>, <AxesSubplot:>]], dtype=object)
Предобработка данных¶
Проводим стандартные операции: поиск явных дубликатов и находим пропущенные значения в ДФ.
Количество явных дубликатов равно 0.
Получили список столбцов и ол-во пропущенных в них данных. В дальнейшем для анализа ДФ. необходимо будет избавиться от пропущенных значений.
print("Кол-во явных дубликатов", data.duplicated().sum())
print("Кол-во пропусков",data.isna().sum(),'\n \n')
Кол-во явных дубликатов 0 Кол-во пропусков total_images 0 last_price 0 total_area 0 first_day_exposition 0 rooms 0 ceiling_height 9195 floors_total 86 living_area 1903 floor 0 is_apartment 20924 studio 0 open_plan 0 kitchen_area 2278 balcony 11519 locality_name 49 airports_nearest 5542 cityCenters_nearest 5519 parks_around3000 5518 parks_nearest 15620 ponds_around3000 5518 ponds_nearest 14589 days_exposition 3181 dtype: int64
Преобразование данных¶
Для удобной и правильной работы с данными. нам нужно привести название колонок к "змеинному_регистру".
data.rename(columns={'cityCenters_nearest':'city_centers_nearest','parks_around3000':'parks_around_3000',
'ponds_around3000':'ponds_around_3000'}, inplace= True) #приводим названия в соответствие
Создаем список колонок где данные должны быть целочисленные,а также данные которые можно привести к этому типу без потери качественных значений.
Далее в цикле мы передаем каждый аргумент названия столбца из списка и преобразуем данные по типу целочисленного, а пропущенные значения приравниваем к '0'
col_in =['airports_nearest', 'balcony',
'city_centers_nearest', 'days_exposition',
'floors_total', 'last_price',
'parks_around_3000', 'parks_nearest',
'ponds_around_3000', 'ponds_nearest' ] #создаем список список для исправления NaN и преобразование типов
for i in col_in:
data[i] = data[i].fillna(0) #заменяем на 0
data[i] = data[i].astype('int')# преобразуем к типу целочисленных
data['first_day_exposition']=pd.to_datetime(data['first_day_exposition'], format='%Y.%m.%dT%H:%M:%S')# преобразуем в тип дата
Изменяем пропущеные значения на 0.
data['is_apartment'] = data['is_apartment'].fillna(False) # Усли не указали что это аппартаменты, скореет всего это обычное жилье
#print('Кореляция ',data['kitchen_area'].corr(data['total_area']))
data['kitchen_area'] = data['kitchen_area'].fillna(0) # корреляция не выявила связи площади кухни
# с общей площадью и жилой. Восстановить данные нельзя. Меняем на 0.
data['ceiling_height'] = data['ceiling_height'].fillna(0)
print('Средняя площадь квартир где 0 комнат :', data.loc[(data['rooms'] == 0)]['total_area'].mean(), '\n')
Средняя площадь квартир где 0 комнат : 29.279746192893406
*** Делаем выборку по данным (типовые) где отсутствуют аномальные значения и выбросы.***
*** Не вбрасываем строки по следующим колонкам: кол-во балконов, расстояние до центра, расстояние до аэропорта,наличие парков, кол-во дней объявления. Это мы не делаем по той причине, что в других столбцах по этим строкам есть правдоподобные данные и терять их не стоит. В дальнейшем при работе с этими столбцами, где нулевые значения, необходимо будет делать выборку***
data = data.loc[data['total_images'] <= 19]#
data = data.loc[(data['total_area'] >=10) & (data['total_area'] <= 250)]#
data = data.loc[(data['floors_total'] >= 2) & (data['floors_total'] <= 30)]#
data = data.loc[(data['last_price'] < 28000000)&(data['last_price'] >121900)]#в указанных колнках выбрали диапазон без выбросов и аномальных данных (типовые данные)
data = data.loc[(data['kitchen_area'] >= 4) & (data['kitchen_area'] < 45)]#
data.dropna(subset=['locality_name'], axis=0, inplace=True) #удаляем строки без обозначения населенного пункта
Восстановим данные в колонке жилая площадь и высота потолков
ratio_area = (data['living_area'] / data['total_area']).sort_values().dropna().mean().round(3) # соотножение жилой и общей площади
print('Кореляция до восстановления данных',data['total_area'].corr(data['living_area']))
data['living_area'] = data['living_area'].fillna(data['total_area'] * ratio_area)# воостанавливаем площадь жилых помещений
print('Кореляция после восстановления данных',data['total_area'].corr(data['living_area']))# проверяем корреляцию после восстановления данных
data =data.reset_index(drop=True)
for k in range(len(data['ceiling_height'])):#устраним ошибки по высоте потолков
if data.loc[k,'ceiling_height'] >= 20 :
data.loc[k,'ceiling_height'] = data.loc[k,'ceiling_height'] / 10
if (data.loc[k,'ceiling_height'] > 10)& (data.loc[k,'ceiling_height'] < 20):
data.loc[k,'ceiling_height'] = 0
data = data.loc[data['ceiling_height'] < 5.2]
data.query('kitchen_area > 0 & living_area > 0 & (total_area * 0.9) >= kitchen_area + living_area')#удалим ошибочные данные по площадям
data =data.reset_index(drop=True)
data.hist(figsize=(15,15), bins=50)# посмотрим как изменились данные
plt.show()
Кореляция до восстановления данных 0.9309742573912947 Кореляция после восстановления данных 0.9321729275593504
1) total_area >= 20
2) kitchen_area >= 4
3)floors_total >=2
Остальные колонки где есть выбросы околоно 0, остались не тронутыми. Т.к. в строках содержаться правдоподобные данные и их много, было бы ошибкой выкидывать строки с ошибкой в одном столбце( тем более что в этих столбцах не основные исследуемые данные). В дальнейшем при работе с этими колонками придется учитывать что у нас есть 0 значения.
1) С рецензией согласен)
2)Удалил из кода фильтрацию по комнатам > 0
3) Да, квартиры с "0" комнат это скорее всего открытая планировка( или квартиры студии) S(mean) = 29.3 .
Обработка не явных дубликатов¶
data['locality_name'] = data['locality_name'].str.lower() #приводим к нижнему регистру.
for i in range(len(data['locality_name'])):
#избавляемся от буквы 'Ё' , городской поселок --> поселок городского типа
if 'ё' in data.loc[i,'locality_name']:
data.loc[i,'locality_name']=data.loc[i,'locality_name'].replace('ё','е')
if 'городской поселок' in data.loc[i,'locality_name']:
data.loc[i,'locality_name']=data.loc[i,'locality_name'].replace('городской поселок','поселок городского типа')
#print(data['locality_name'].unique(),'\n'*3) для изучения содержания
# исправляем выбившиеся значения (есть название и есть названия+ принадлежность)
if ('поселок' not in data.loc[i,'locality_name']) & \
('мурино' in data.loc[i,'locality_name']):
data.loc[i,'locality_name']=data.loc[i,'locality_name'].replace('мурино','поселок мурино')
if ('деревня' not in data.loc[i,'locality_name']) & \
('кудрово' in data.loc[i,'locality_name']):
data.loc[i,'locality_name']=data.loc[i,'locality_name'].replace('кудрово','деревня кудрово')
if ('село' not in data.loc[i,'locality_name']) & \
('никольское' in data.loc[i,'locality_name']):
data.loc[i,'locality_name']=data.loc[i,'locality_name'].replace('никольское','село никольское')
print(data['locality_name'].unique(),'\n'*3) #выводим уникальные значения для проверки
#print(data.duplicated().sum()) после всех исправлений посмотрим дубликаты
['поселок шушары' 'санкт-петербург' 'поселок городского типа янино-1' 'поселок парголово' 'ломоносов' 'сертолово' 'пушкин' 'колпино' 'поселок мурино' 'петергоф' 'гатчина' 'деревня федоровское' 'выборг' 'кронштадт' 'кировск' 'деревня новое девяткино' 'поселок металлострой' 'поселок городского типа лебяжье' 'поселок городского типа сиверский' 'поселок городского типа кузьмоловский' 'садовое товарищество новая ропша' 'павловск' 'деревня пикколово' 'всеволожск' 'кингисепп' 'приозерск' 'сестрорецк' 'деревня куттузи' 'поселок аннино' 'деревня заклинье' 'поселок торковичи' 'красное село' 'поселок понтонный' 'деревня старая' 'село путилово' 'ивангород' 'сланцы' 'шлиссельбург' 'сясьстрой' 'село никольское' 'зеленогорск' 'сосновый бор' 'поселок новый свет' 'деревня кудрово' 'деревня оржицы' 'деревня кальтино' 'поселок романовка' 'поселок бугры' 'волхов' 'поселок городского типа рощино' 'кириши' 'луга' 'волосово' 'отрадное' 'село павлово' 'поселок оредеж' 'поселок городского типа красный бор' 'коммунар' 'поселок молодежное' 'поселок победа' 'деревня нурма' 'поселок городского типа синявино' 'тосно' 'поселок стрельна' 'бокситогорск' 'поселок александровская' 'деревня лопухинка' 'поселок терволово' 'поселок городского типа советский' 'подпорожье' 'поселок сельцо' 'поселок городского типа вырица' 'деревня келози' 'деревня вартемяги' 'поселок тельмана' 'поселок городского типа большая ижора' 'тихвин' 'деревня агалатово' 'поселок новогорелово' 'поселок городского типа лесогорский' 'деревня лаголово' 'поселок цвелодубово' 'поселок городского типа рахья' 'деревня белогорка' 'поселок заводской' 'поселок городского типа новоселье' 'деревня большие колпаны' 'деревня горбунки' 'поселок городского типа токсово' 'приморск' 'поселок городского типа федоровское' 'деревня мистолово' 'новая ладога' 'поселок барышево' 'деревня разметелево' 'поселок городского типа имени свердлова' 'деревня пеники' 'поселок рябово' 'деревня пудомяги' 'деревня бегуницы' 'поселок поляны' 'поселок городского типа мга' 'поселок елизаветино' 'поселок городского типа кузнечное' 'деревня колтуши' 'поселок запорожское' 'поселок молодцово' 'деревня гостилицы' 'деревня малое карлино' 'поселок мичуринское' 'поселок городского типа имени морозова' 'поселок песочный' 'поселок сосново' 'деревня аро' 'поселок ильичево' 'поселок городского типа тайцы' 'деревня малое верево' 'деревня извара' 'поселок станции вещево' 'деревня калитино' 'поселок городского типа ульяновка' 'деревня чудской бор' 'поселок городского типа дубровка' 'деревня мины' 'поселок войсковицы' 'деревня коркино' 'поселок ропша' 'поселок первомайское' 'поселок городского типа приладожский' 'поселок щеглово' 'поселок гаврилово' 'лодейное поле' 'пикалево' 'деревня рабитицы' 'деревня кузьмолово' 'деревня малые колпаны' 'поселок городского типа назия' 'поселок городского типа павлово' 'поселок углово' 'деревня низино' 'поселок старая малукса' 'садовое товарищество рахья' 'деревня меньково' 'деревня старые бегуницы' 'поселок саперный' 'поселок семрино' 'поселок глажево' 'поселок кобринское' 'деревня гарболово' 'деревня юкки' 'поселок станции приветнинское' 'поселок зимитицы' 'деревня мануйлово' 'деревня пчева' 'поселок цвылево' 'поселок мельниково' 'поселок плодовое' 'поселок пудость' 'поселок усть-луга' 'светогорск' 'любань' 'поселок селезнево' 'поселок городского типа рябово' 'каменногорск' 'деревня кривко' 'поселок глебычево' 'деревня парицы' 'поселок жилпоселок' 'поселок войскорово' 'поселок стеклянный' 'поселок мыза-ивановка' 'село русско-высоцкое' 'поселок городского типа форносово' 'поселок житково' 'поселок городского типа виллози' 'деревня лампово' 'деревня шпаньково' 'деревня кипень' 'поселок сумино' 'поселок возрождение' 'деревня старосиверская' 'поселок кикерино' 'деревня старое хинколово' 'поселок пригородный' 'поселок торфяное' 'поселок суходолье' 'поселок красная долина' 'деревня заневка' 'поселок городского типа дружная горка' 'поселок лисий нос' 'деревня яльгелево' 'село рождествено' 'деревня сяськелево' 'деревня камышовка' 'садоводческое некоммерческое товарищество лесная поляна' 'поселок жилгородок' 'деревня ялгино' 'деревня батово' 'поселок новый учхоз' 'поселок гончарово' 'поселок почап' 'поселок саперное' 'поселок платформа 69-й километр' 'поселок каложицы' 'деревня фалилеево' 'деревня пельгора' 'деревня торошковичи' 'поселок белоостров' 'поселок алексеевка' 'поселок городского типа важины' 'деревня лесколово' 'поселок лукаши' 'поселок петровское' 'деревня щеглово' 'поселок городского типа никольский' 'поселок кингисеппский' 'поселок при железнодорожной станции вещево' 'поселок ушаки' 'деревня старополье' 'деревня котлы' 'деревня торосово' 'поселок форт красная горка' 'деревня новолисино' 'поселок станции громово' 'поселок городского типа ефимовский' 'деревня глинка' 'деревня старая пустошь' 'поселок коммунары' 'поселок репино' 'деревня разбегаево' 'поселок гладкое' 'поселок при железнодорожной станции приветнинское' 'поселок тесово-4' 'деревня бор' 'поселок коробицыно' 'деревня большая вруда' 'деревня курковицы' 'поселок серебрянский' 'поселок кобралово' 'деревня суоранда' 'поселок городского типа кондратьево' 'село копорье' 'поселок починок' 'поселок любань' 'деревня реброво' 'поселок городского типа будогощь' 'деревня зимитицы' 'деревня тойворово' 'поселок семиозерье' 'поселок лесное' 'поселок совхозный' 'поселок суйда' 'деревня нижние осельки' 'поселок перово' 'высоцк' 'поселок гарболово' 'село шум' 'поселок котельский' 'поселок ленинское' 'деревня большая пустомержа' 'деревня пижма' 'коттеджный поселок кивеннапа север' 'поселок ромашки' 'деревня куровицы' 'поселок кирпичное' 'деревня ям-тесово' 'поселок городского типа вознесенье' 'поселок шугозеро' 'деревня ваганово' 'поселок пушное' 'садовое товарищество садко' 'деревня выскатка' 'поселок громово' 'поселок станции свирь' 'деревня кисельня' 'село старая ладога' 'поселок калитино' 'поселок высокоключевой' 'садовое товарищество приладожский' 'поселок пансионат зеленый бор' 'деревня ненимяки' 'деревня снегиревка' 'деревня рапполово' 'деревня пустынка' 'поселок рабитицы' 'деревня большой сабск' 'поселок усть-ижора' 'деревня лупполово' 'деревня большое рейзино' 'деревня малая романовка' 'поселок дружноселье' 'село паша' 'поселок володарское' 'деревня нижняя' 'коттеджный поселок лесное' 'деревня тихковицы' 'деревня борисова грива' 'поселок дзержинского']
1) Регистр (по сути один и тот-же населенный пункт, но для Python это разные вещи)
2) Буква "Ё", точно также как с регистром Е = Ё, но не для среды.
3) Принадлежность населенного пункта к типу( Кудрово и деревня Кудрово, одно и то же)
Посчитайте и добавьте в таблицу новые столбцы¶
data['price_metr'] = data['last_price'] / data['total_area'] # цена квадратного метра
data['day_week'] = data['first_day_exposition'].dt.weekday # номер дня недели
data['month'] = data['first_day_exposition'].dt.month # месяц
data['year'] = data['first_day_exposition'].dt.year # год
for i in range(len(data['floor'])): # формируем метку расположения квартиры по принадлежности к этажу
if data.loc[i,'floor'] == 1:
data.loc[i,'floor_mark'] ='первый'
elif data.loc[i,'floor'] == data.loc[i,'floors_total']:
data.loc[i,'floor_mark'] ='полследний'
else:
data.loc[i,'floor_mark'] ='другой'
data['center_km'] = (data['city_centers_nearest'] /1000).round(0)
Проведите исследовательский анализ данных¶
data.hist(column='total_area',bins=100)
data.hist(column='living_area',bins=100)
data.loc[data['kitchen_area'] > 0].hist(column='kitchen_area',bins=60)
data.hist(column='last_price',bins=100)
data.hist(column='rooms',bins=10)
data.loc[data['ceiling_height'] > 0].hist(column='ceiling_height',bins=100)
data.hist(column='floors_total',bins=30)
data.loc[data['city_centers_nearest'] > 0].hist(column='city_centers_nearest',bins=100)
data.loc[data['airports_nearest'] > 0].hist(column='airports_nearest',bins=100)
data.loc[data['parks_nearest'] > 0].hist(column='parks_nearest',bins=100)
data.hist(column='day_week',bins=20)
data.hist(column='month',bins=30)
explode = (0, 0.1, 0.15)
data.pivot_table(index='floor_mark',values='last_price',aggfunc='count').plot(kind="pie",
y='last_price',autopct='%1.1f%%', shadow=True, explode = explode)
plt.show()
plt.figure(figsize = (8,8))
sns.heatmap(data[['total_area','living_area','kitchen_area','last_price',
'rooms','ceiling_height','floors_total',
'city_centers_nearest','parks_nearest']].corr(),fmt='.2g',annot = True, cmap= 'coolwarm')
plt.show()
Выводы исследовательского анализа данных¶
Общая площадь: общая площадь по объявлениям от 20 м2 до 230 м2. Наибольшее количество объявлений (типовая площадь) лежит в диапазоне 25-100 м2. В районе 40м2 наблюдается пик, объявлений с такой площадь больше чем других.
Жилая площадь: Диапазон основных данных лежит в пределах 20-65м2 (больше всего таких объявлений). Имеется 3 осеовных пика это: 20м2 , 30 м2 и 40м2. Жилая площадь более 100 м2 очень редка в предложениях опокупке.
Площадь кухни: Данные находятся в промежутке 5-15 м2. Кухни с площадью 20 м2 и более представлены редко.
Стоимость: Гистограмма имеет доволно плавную форму (без провалов и резких пиков). Основной набор данных лежит в пределах от 1 до 15 млн. Наибольшее количество объявлений о продаже в райне 1.5-6.5 млн.
Количество комнат: основную часть объявлений представляют 1-2 комнатные квартиры (~70%), далее идут 3-х комнатные (~23%), остальные (~7%).
Высота потолков: Типовая высота потолков от 2,5 до 3 м. Наибольшее количество предложений с высотой 2.5м.
Количество этажей: Болше всего объявлений содержится в группах 5 и 9 этажей. Следующая группа 10,12,16,24 этажей.
Расстояние до центра: Активнее всего продают кватиры в в удалении от центра на 10-18км.
Расстояние до аэропорта: Идет плавное распределение от 10-54км. Это основные продажи квартир.
Расстояние до парка: Большинство объектов имеет доступ к паркам с расстоянием не более 1км. Пик приходиться на расстояние в 400м.(Видимо в городе много парков)
День размещения объявления: Активность подачи объявлений растет к середине недели затем немного спадает. В выходные дни активность ниже в 2-2.5 раза
Месяц подачи объявления: Самая большая активность наблюдаетсяв в двух периодах, с февраля по апрель и сентябрь-ноябрь. Наиболее пассивные месяцы декабрь, январь и май. Остается еще один отрезок с линейным характеромб это летние месяцы.
ЭтажностьЖ большую часть объявлений составляют квартиры с этажом между пкрвым и последним 73%. Осталвщиеся этажности приблизительно в равных долях ~ 13%
Корреляция: Выявлена сильная связь (0.93) между жилой и общей площадью. Вследствии чего была возможность восстановить данные по площади в ДФ. Также имеется сильная связь между общей площадью и ценой (0.78). И последнее площадь и кол-во комнат (0.8).
Скорость продаж¶
data.hist(column='days_exposition',bins=300)
plt.show()
print('Самая долгая продажа \n',data.loc[(data['days_exposition'] == data['days_exposition'].max())&
(data['days_exposition'] !=0)],'\n'*3)
print('\n Самая быстрая продажа',data.loc[(data['days_exposition'] !=0)]['days_exposition'].min())
print(data.loc[(data['days_exposition'] == 1)],'\n'*2)
print('Медиана:',data.loc[data['days_exposition'] !=0]['days_exposition'].median())
print('Среднее значение:',data.loc[data['days_exposition'] !=0]['days_exposition'].mean())
data.loc[data['days_exposition'] !=0].boxplot(column=['days_exposition'],figsize=(6,10), notch = True)
plt.ylim(0,600)
data.loc[data['days_exposition'] !=0]['days_exposition'].describe()
Самая долгая продажа
total_images last_price total_area first_day_exposition rooms \
15341 11 3500000 48.2 2014-12-15 2
ceiling_height floors_total living_area floor is_apartment ... \
15341 2.5 5 27.4 2 False ...
parks_nearest ponds_around_3000 ponds_nearest days_exposition \
15341 0 0 0 1580
price_metr day_week month year floor_mark center_km
15341 72614.107884 0 12 2014 другой 0.0
[1 rows x 28 columns]
Самая быстрая продажа 1
total_images last_price total_area first_day_exposition rooms \
1345 19 4000000 49.9 2019-05-01 2
ceiling_height floors_total living_area floor is_apartment ... \
1345 2.5 9 25.0 1 False ...
parks_nearest ponds_around_3000 ponds_nearest days_exposition \
1345 20 1 681 1
price_metr day_week month year floor_mark center_km
1345 80160.320641 2 5 2019 первый 14.0
[1 rows x 28 columns]
Медиана: 100.0
Среднее значение: 184.53295197235133
count 16782.000000 mean 184.532952 std 221.314424 min 1.000000 25% 45.000000 50% 100.000000 75% 238.000000 max 1580.000000 Name: days_exposition, dtype: float64
Продажи распределились следующим образом: "45<= быстрая продажа " | "45> <229" обычные продажи | "229> долгие продажи ". Продажи более 500 дней это аномально долгие Медиана по прадажам составила 93 дня.
Факторы влияния¶
sns.barplot(data=data,
y='last_price',
x='year')
plt.show()
sns.barplot(data=data,y='last_price',x='day_week')
plt.show()
sns.barplot(data=data, y='last_price',x='month')
plt.show()
data.hist(column='month',bins=30)
plt.show()
sns.barplot(data=data, y='last_price',x='floor_mark')
plt.show()
plt.figure(figsize = (6,6))
sns.heatmap(data[['last_price','total_area','living_area','kitchen_area','rooms']].corr(), fmt='.2g', annot = True, vmin=-1, vmax=1, center= 0, cmap= 'coolwarm')
plt.show()
plt.title('Зависимость цены от площади', color ='brown')
plt.scatter(data = data, x='total_area', y='last_price')
plt.show()
plt.title('Зависимость цены от жилой площади', color ='brown')
plt.scatter(data = data, x='living_area', y='last_price')
plt.show()
plt.title('Зависимость цены от площади кухни', color ='brown')
plt.scatter(data = data, x='kitchen_area', y='last_price')
plt.show()
price_rooms = data.loc[data['rooms'] >= 1].pivot_table(index =['rooms'], values=['last_price'], aggfunc ='mean' )
plt.title('Цена от количества комнат', color='brown')
plt.plot(price_rooms)
plt.show()
Максимальные цены на жилье были в 2014 году. Затем в 2015г. идет резкий спад далее спад продолжается но плавно и медленно.
Цена варьируется в завсимости от дня недели. С начала до середины идет плавный подъем, далее плавный спад. На выходных происходит более сильная просадка в цене.
Цены на квартиры первого и последнего этажа ниже чем на другие.
Зависимость цены от месяца: цена плавно варьируется в течении года. Явной зависимости не прослеживается. Здесь просматривается другая зависимость, если посмотреть этот график и график кол-во объявлений по месяцам, то увидим где мало объявлений там цена растет, а где объявлений больше цена падает.
Зависимость цены от кол-ва комнат в интервале от 1 до 7 линейная, далее начинается разброс.
Самый малый разброс значений в граффиках площади и цены, это граффик цены от общай площади. Корреляция это нам подтверждает.
Вывод: Влияние на цену в порядке убывания: количество комнат, общая площадь,этаж, месяц, день недели. Так-же на цену влияет очень сильно год, но это не систематическое влияние,а подтверждение что произошло что-то глобального характера.
Средняя цена м2¶
data_pi = data.pivot_table(index =['locality_name'], values=['total_area'], aggfunc ='count' )
data_pi.rename(columns={'total_area':'number_ads'}, inplace= True)
data_pi = data_pi.sort_values('number_ads',ascending =False)
data_pi.reset_index(inplace= True)
for i in range(len(data_pi)):
data_pi.loc[ i, 'price_square_mean'] = (data.loc[data['locality_name']
== data_pi.loc[i,'locality_name']]['price_metr'].mean())
display(data_pi.head(10))
print('Минимальная цена за квадратный метр \n',
data_pi.loc[data_pi['price_square_mean'] ==data_pi['price_square_mean'].min()],'\n')
print('Максимальная цена за квадратный метр \n',
data_pi.loc[data_pi['price_square_mean'] ==data_pi['price_square_mean'].max()],'\n')
#display(data_pi.sort_values('price_square_mean',ascending =False))
| locality_name | number_ads | price_square_mean | |
|---|---|---|---|
| 0 | санкт-петербург | 12734 | 108694.115170 |
| 1 | поселок мурино | 449 | 85300.148732 |
| 2 | поселок шушары | 376 | 78007.905130 |
| 3 | деревня кудрово | 342 | 94153.665248 |
| 4 | всеволожск | 322 | 68970.912824 |
| 5 | колпино | 311 | 75047.650814 |
| 6 | пушкин | 306 | 101262.140143 |
| 7 | гатчина | 282 | 68192.127717 |
| 8 | поселок парголово | 276 | 90179.137423 |
| 9 | выборг | 197 | 58163.604578 |
Минимальная цена за квадратный метр
locality_name number_ads price_square_mean
226 деревня старополье 1 10368.663594
Максимальная цена за квадратный метр
locality_name number_ads price_square_mean
46 зеленогорск 22 114070.944645
#print(data.loc[(data['locality_name'] == 'санкт-петербург')&
# (data['last_price'] > 0)&
# (data['center_km'] > 0)]['last_price'].corr(data['center_km']))
#data['mean_km'] = (data.loc[(data['locality_name'] == 'санкт-петербург')&(data['center_km'] > 0)]['last_price']
# / data.loc[(data['locality_name'] == 'санкт-петербург')&(data['center_km'] > 0)]['center_km'])
#data['mean_km'] = data['mean_km'].fillna(0)
#data.loc[(data['locality_name'] == 'санкт-петербург') &
# (data['center_km'] > 0)].plot(kind='scatter', x='last_price',y='center_km')
#data.loc[(data['locality_name'] == 'санкт-петербург') &
# (data['mean_km'] > 0)].plot(kind='scatter', x='center_km',y='mean_km')
mean_km = {}
for i in range(1,67) :
mean_km[i] = (data.query('center_km != 0 & center_km <= @i & center_km > @i-1')['last_price'].mean())
mean_km_df = []
mean_km_df = pd.DataFrame(pd.DataFrame(list(mean_km.items()),
columns=['distance', 'sel_price']))
mean_km_df = mean_km_df.dropna()
mean_km_df.reset_index(inplace= True)
plt.title('Зависимость цены километра от расстояния', color ='brown')
plt.plot(mean_km_df['distance'], mean_km_df['sel_price'])
print(mean_km_df.head(10))
index distance sel_price 0 0 1 1.119733e+07 1 1 2 1.057461e+07 2 2 3 9.197928e+06 3 3 4 9.965765e+06 4 4 5 1.020196e+07 5 5 6 9.267227e+06 6 6 7 8.462508e+06 7 7 8 8.539599e+06 8 8 9 6.519775e+06 9 9 10 6.175360e+06
При удалении от центра цена на на площади падает. Это корошо показываtт граффик. Особое внимание на график зависимости средней цены за километр от удаленности в километрах. Чем дальше от центра тем цена 1м2 ниже. Близко к центру квадратные метры очень дорогие (напоминает exp)
Имеется пик на удалении в 55км. Похоже есть элитный поселок.
- ... вычислите среднюю цену каждого километра
То есть тут нужно определить средние по каждому километру отдельно, по диаграмме рассеяния средние довольно сложно понять, тут лучше подойдет линейный график
Общий вывод¶
Проведя исследовательский анализ предоставленных данныч можно придти к следующим вывода:
Наибольшее влияние на цену недвижимости оказывает общая площадь. Но также стоит уделить особое внимание двум вещам: во-первых это зависимость цены от года (системного влияния нет, но влияние крайне сильное),а во-вторых что касается Санкт-Петербурга болше всего на цену влияетблизость к центру (чем ближе тем дороже, экспоненциальная зависимость)
Следующие факторы влияющие на цену недвижимости: этаж, месяц, день недели (размещены в порядке влияния: от большего к меньшему).
Срез по длительности публикации: продажи длительностью менее 46 дней это быстрые продажи,от 46 до 229 дней это типовое время продажи, более 229 это долгие продажи.Продажи более 500 дней это аномально долгие.
Чек-лист готовности проекта
Поставьте 'x' в выполненных пунктах. Далее нажмите Shift+Enter.
- открыт файл
- файлы изучены (выведены первые строки, метод
info(), гистограммы и т.д.) - определены пропущенные значения
- заполнены пропущенные значения там, где это возможно
- есть пояснение, какие пропущенные значения обнаружены
- изменены типы данных
- есть пояснение, в каких столбцах изменены типы и почему
- устранены неявные дубликаты в названиях населённых пунктов
- устранены редкие и выбивающиеся значения (аномалии) во всех столбцах
- посчитано и добавлено в таблицу: цена одного квадратного метра
- посчитано и добавлено в таблицу: день публикации объявления (0 - понедельник, 1 - вторник и т.д.)
- посчитано и добавлено в таблицу: месяц публикации объявления
- посчитано и добавлено в таблицу: год публикации объявления
- посчитано и добавлено в таблицу: тип этажа квартиры (значения — «первый», «последний», «другой»)
- посчитано и добавлено в таблицу: расстояние в км до центра города
- изучены и описаны следующие параметры: - общая площадь; - жилая площадь; - площадь кухни; - цена объекта; - количество комнат; - высота потолков; - этаж квартиры; - тип этажа квартиры («первый», «последний», «другой»); - общее количество этажей в доме; - расстояние до центра города в метрах; - расстояние до ближайшего аэропорта; - расстояние до ближайшего парка; - день и месяц публикации объявления
- построены гистограммы для каждого параметра
- выполнено задание: "Изучите, как быстро продавались квартиры (столбец days_exposition). Этот параметр показывает, сколько дней «висело» каждое объявление.
- Постройте гистограмму.
- Посчитайте среднее и медиану.
- В ячейке типа markdown опишите, сколько обычно занимает продажа. Какие продажи можно считать быстрыми, а какие — необычно долгими?"
- выполнено задание: "Какие факторы больше всего влияют на общую (полную) стоимость объекта? Постройте графики, которые покажут зависимость цены от указанных ниже параметров. Для подготовки данных перед визуализацией вы можете использовать сводные таблицы." - общей площади; - жилой площади; - площади кухни; - количество комнат; - типа этажа, на котором расположена квартира (первый, последний, другой); - даты размещения (день недели, месяц, год);
- выполнено задание: "Посчитайте среднюю цену одного квадратного метра в 10 населённых пунктах с наибольшим числом объявлений. Выделите населённые пункты с самой высокой и низкой стоимостью квадратного метра. Эти данные можно найти по имени в столбце
locality_name." - выполнено задание: "Ранее вы посчитали расстояние до центра в километрах. Теперь выделите квартиры в Санкт-Петербурге с помощью столбца
locality_nameи вычислите среднюю цену каждого километра. Опишите, как стоимость объектов зависит от расстояния до центра города." - в каждом этапе есть промежуточные выводы
- есть общий вывод