Этот набор данных содержит информацию обо всех типах строительных разрешений с 1 января 2013 года по 25 февраля 2018 (почти 200к записей). Это не обязательно должно быть разрешение на строительство нового здания, надо также получать одобрение на изменение фасада, этажности, количества составных частей здания. А также при проведении трубопроводов, электричества, изменении планировки. Если кто то загорелся желанием узнать поподробнее, то вот ссылка с более подробным описанием строительных разрешений. Вышесказанное означает, что какие то признаки в строках, ожидаемо, будут иметь значение NaN, так как если мы хотим построить здание, то его существующая этажность не то чтобы 0. Ее попросту нет, как и материалов из которых здание существует (ведь оно не существует - спасибо кэп).
Данные настоящие и обновляются каждую субботу, спасибо открытому порталу Сан-Франциско.
import pandas as pd
import warnings
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline
warnings.filterwarnings('ignore')
Ссылка по которой можно найти данные
df = pd.read_csv('./data/Building_Permits.csv', sep=',')
df.info()
Параметров очень много, как и их значений. Разберемся по порядку. Без паники. Сначала посмотрим ближе на самый интересный из всех:
# текущее состояние заявки
# это и будет наш целевой признак
df['Current Status'].value_counts()
Глубоко вникать в определение этих терминов можно долго (и это, будем честны, требует знаний того, как устроена работа в подобных департаментах). Но видно что они разделены на две основных группы: заявка одобрена и не одобрена.
Ну а теперь время узнать, какие свойства можно будет использовать для предсказания судьб будущих заявок (жирным выделены наиболее интересные для изучения, то есть те, что, возможно, будут сильнее всего влиять на целевой признак):
Наконец, рассмотрим какие типы запросов (разрешений) поступают в департамент:
df['Permit Type Definition'].value_counts()
Вернемся к целевому признаку Current Status и немного прорядим данные. Заявки, которые на момент работы с данными находятся в обработке, ничем не помогут нашей модели, которая будет определять: разрешать ли стройку или нет. Также, например, если заявитель отозвал свою заявку, то никакой информации о решении департамента мы не имеем. Следовательно, подобные записи можно удалить (помечены ниже красным).
df = df[(df['Current Status'] != 'filed') &
(df['Current Status'] != 'withdrawn') &
(df['Current Status'] != 'expired') &
(df['Current Status'] != 'plancheck') &
(df['Current Status'] != 'disapproved') &
(df['Current Status'] != 'appeal') ]
Посмотрим на процентное соотношение классов между собой:
df['Current Status'].value_counts()/df.shape[0]*100
Видно, что распределение классов крайне не равномерное.
Так как мы поставили перед собой задачу создать модель, которая принимает решение о выдаче разрешения на строительные работы, то отобразим множество упомянутых выше классов на множество {0, 1} где 0 - отказать в запросе, 1 - одобрить проект.
df['Current Status'] = df['Current Status'].map({'cancelled': 0, 'suspend': 0, 'revoked': 0,
'complete': 1, 'issued': 1, 'approved': 1,
'reinstated': 1, 'incomplete': 1})
df['Current Status'] = df['Current Status'].astype('int64')
print('Распределение классов в процентах:')
df['Current Status'].value_counts() /df.shape[0] * 100
Ан нет... Пора спать, завтра важная пара с утра, а я с Новосибирска (+4 от Мск). Но можно же несколько баллов заработать за первые два пунтка все равно, так? :D
Если это дойдет до глаз читателей, то прошу прощения, за украденное время. Хорошего дня :)