نگاهی به داده های مسکن در شهر تهران

در این پست نگاهی به داده های مسکن در شهر تهران میندازیم و سعی میکنیم با ابزارهای مختلف تحلیلی روی این داده ها داشته باشیم. برای این کار از بخشی از داده های وبسایت کیلید استفاده میکنیم که خدمات متنوعی در حوزه املاک ارائه میده. این داده ها مربوط به آگهی های فروش املاک مسکونی در مناطق مختلف تهران هست و از تیر تا بهمن سال 97 رو شامل میشه. در بخش اول به تحلیل توصیفی داده ها می پردازیم که بخش مهمی از پروژه های تحلیل داده رو شامل میشه. برای این منظور از نرم افزار معروف شرکت مایکروسافت power bi استفاده میکنیم که طبق گزارش شرکت گارتنر از بهترین ابزارهای حوزه هوش تجاری به حساب میاد.

بخش اول

پیش نوشت: همون طور که میدونید، خونه های لوکس قیمت های بالایی دارن که خیلی وقتا چند برابر خونه های معمولی قیمت گذاری میشن. به همین دلیل برای توصیف شاخص مرکزی در این گزارش بیشتر از میانه استفاده میکنیم (مثلا میانه قیمت خانه در منطقه 5) چون کمتر از میانگین به مقادیر پرت (outlier) حساسه و کمتر تحت تاثیر این اختلاف ارقام قرار میگیره (میانه به زبان ساده نقطه ای هست که نیمی از داده ها از اون بزرگتر و نیمی دیگه از داده ها از اون کوچک تر هستن مثلا در مورد مجموعه اعداد 1،2،3،5،9 عدد 3 میانه حساب میشه).در ادامه لینک گزارش رو برای دسترسی شما قرار میدم و به بررسی اون میپردازیم.

لینک گزارش power bi

صفحه اول داشبورد شامل سه شکل مختلف و یک فیلتر برای اعمال تغییرات موردنظر میشه که در ادامه به بررسی اونها می پردازیم. مطابق تصویر زیر با انتخاب فیلتر سمت راست میتونیم به لایه های جزیی تر گزارش بریم. کنار فیلتر نمودار میله ای وجود داره که تعداد اگهی ها رو در مناطق مختلف تهران نشون میده که منطقه پنج بیشترین تعداد اگهی ها رو در سایت داشته. اگه روی نمودار کلیک کنیم میتونیم از سال به ماه و سپس روزهای هر ماه بریم. کنار همین نمودار میله ای موقعیت جغرافیایی نمونه ها و اسم محله رو میبینیم. اندازه هر دایره میانگین قیمت هر متر در اون ناحیه رو نشون میده و همون طور که مشخصه مناطق شمالی دایره های بزرگتر و خونه های گرون قیمت تری رو دارن. آخرین شکل در پایین صفحه فیمت ملک نسبت به مساحت دیده میشه و میتونیم ببینیم خونه های مختلف بر حسب مساحت چقدر قیمت گذاری شدن (که البته برای املاکی که کمتر از 500 متر و قیمت کمتر از 5 میلیارد فیلتر شدن).

صفحه اول داشبورد
صفحه اول داشبورد


در صفحه دوم گزارش که با کلیک در پایین صفحه گزارش انجام میشه سه شکل متفاوت وجود داره.

نحوه رفتن به صفحه دوم
نحوه رفتن به صفحه دوم


صفحه دوم گزارش
صفحه دوم گزارش


در شکل سمت چپ امکان مقایسه میانگین و میانه قیمت در مناطق مختلف وجود داره. همون طور که قبلا اشاره شد در مورد شاخص های مرکزی میانگین به داده های غیر عادی یا پرت حساس تر هست و هرقدر داده ها به صورت نرمال توزیع شده باشن میانه و میانگین به هم نزدیکترن. در مورد داده های مسکن در مناطقی مثل 1و2و3 میانگین ومیانه فاصله زیادی از هم دارن و نشون میده در اون مناطق خونه های گرون قیمتی نسبت به سایر خونه ها زیادی وجود داره. درحالیکه در مناطقی مثل 9و21و19 این طور نیست.

شکل بالا سمت راست، تغییرات قیمت نسبت به زمان رو نشون میده. البته به لطف حالت تعاملی داشبورد میتونیم با کلیک روی منطقه خاصی از شکل های دیگه این تغییرات رو در هر منطقه به صورت حداگانه ببینیم

آخرین شکل در این صفحه به مقایسه تغییرات قیمت نسبت به مساحت در مناطق مختلف شهرداری مربوط میشه.


بخش دوم

در این قسمت از زبان برنامه نویسی پایتون استفاده میکنیم که در سال های اخیر کاربرد وسیعی در مسائل تحلیل داده پیدا کرده. قصد داریم به کمک یکی از پرکاربردترین الگوریتم های یادگیری ماشین یعنی رگرسیون خطی به مدلی ساده از قیمت مسکن که قابلیت پیش بینی داشته باشه برسیم. رگرسیون در ساده ترین حالت مدلیه که از تعدادی متغیر مستقل و یک متغیر وابسته تشکیل شده و هدف پیدا کردن بهترین ضرایب برای متغیرهای مستقل جهت تبیین متغیر وابسته هست.

قبل از اینکه داده ها رو بتونیم به عنوان ورودی به مدل بدیم باید داده ها رو اصطلاحا پیش پردازش (preprocessing) کنیم که شامل حذف یا اصلاح داده های کثیف، آماده سازی متغیرها و... میشه. این بخش مهمترین قسمت کاره که تا هشتاد درصد وقت رو به خودش اختصاص میده. ابتدا داده ها رو با پکیج pandas فراخوانی میکنیم. در اینجا 70000 سطر ابتدایی داده ها استفاده شده و سطرهایی که دارای داده گمشده (null) بودن حذف شدن (البته در مواردی لازمه که با روش هایی مثل میانگین گرفتن یا الگوریتم های یادگیری ماشین، این داده ها جایگزین بشن).

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
data=pd.read_csv ("...\kilid.csv",nrows=70000)
data.dropna(subset=['region','landuseType','noBeds', 'floorArea','price'],inplace=True)
پنج سطر ابتدایی داده ها
پنج سطر ابتدایی داده ها

یکی دیگه از مواردی که قبلا اشاره شد وجود داده های غیر طبیعی، نویز یا پرت (outlier) در داده هاست. این موارد غیرطبیعی باعث سردرگمی مدل ما میشن. در این مورد ما ساده ترین رویکرد رو انتخاب میکنیم به این صورت که از 5 درصد ابتدایی و انتهایی داده ها صرف نظر میکنیم (مواردی که قیمت خیلی پایین یا خیلی بالایی دارن از مجموعه حذف میکنیم) سپس متغیر قیمت خانه رو به عنوان متغیر وابسته که قصد پیشبینی مقدار اون رو داریم (y) و سایر متغیرها رو به عنوان متغیر وابسته (x) در نظر میگیریم.

P = np.percentile(data['price'], [5, 95])
new_df = data[(data['price'] > P[0]) & (data['price'] < P[1])]
X=new_df[['landuseType','region','noBeds', 'floorArea']].values
y=new_df.price.values.reshape(-1,1)

ثالدر مرحله بعد برای آماده سازی متغیرها و اجرای الگوریتم از پکیج sklearn استفاده میکنیم. حالا باید متغیرهایی که غیررتبه ای هستن به متغیرهای رتبه ای تبدیل کنیم. در مورد داده های ما مناطق مختلف شهرداری حالت غیر رتبه ای دارن یعنی مثلا در پیش بینی قیمت ملک فاصله منطقه پنج و شش با فاصله منطقه شش و هفت یک واحد نیست و همین طور فاصله منطقه دوازده از منطقه دو 10 واحد نیست و اعداد صرفا اسم اون منطقه محسوب میشن. در حالی که در مورد متغیر دیگه ( مساحت خانه) فاصله 71 متری از 70 متری مثل 81متری از متری و همین طور 80 متری تا 70 متری دقیقا 10 واحد هست. پس مطابق مثال زیر که اسامی کشورها به ستون های مجزا تبدیل شده، متغیر منطقه شهرداری در مدل ما به ستون های مجزا تقسیم میشه (از یک ستون به 22 ستون برای مناطق 22 گانه) هر چند برای جلوگیری از بروز همخطی چندگانه (multicollinearity) باید یکی از آنها را حذف کنیم.

نحوه تبدیل داده های اسمی به عددی(رتبه ای)
نحوه تبدیل داده های اسمی به عددی(رتبه ای)


from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder = LabelEncoder()
X[:, 0] = labelencoder.fit_transform(X[:, 0])
X[:, 1] = labelencoder.fit_transform(X[:, 1])
onehotencoder = OneHotEncoder(categorical_features = [0,1])
X = onehotencoder.fit_transform(X).toarray()
X = X[:, 1:]

اما در مورد مساحت خانه رابطه بین مساحت خانه و قیمت، الزاما یک رابطه خطی نیست (افزایش قیمت به ازای افزایش مساحت از 70 متر به 71متر با افزایش قیمت به ازای افزایش مساحت از 100 به 101 متر یکسان نیست و معمولا خانه های بزرگتر با شیب کمتری گرون میشن).

تفاوت رابطه خطی و غیر خطی
تفاوت رابطه خطی و غیر خطی


برای افزایش انعطاف مدل در این مورد از متغیر درجه دوم(توان دوم مساحت خانه) استفاده میکنیم.

from sklearn.preprocessing import PolynomialFeatures
X_poly=PolynomialFeatures().fit_transform(X[:,-1].reshape(-1,1))
X=np.append(X,X_poly,axis=1)

در نهایت برای اینکه بتونیم دقت مدلمون رو بسنجیم باید بخشی از داده ها رو به عنوان داده های آموزش (train) جدا کنیم و از اون برای آموزش مدل استفاده کنیم و بخش دیگه رو (test) فقط برای ارزیابی مدل استفاده کنیم (در اینجا 80 درصد آموزش و 20 درصد تست).

from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X_train, y_train)
y_pred = regressor.predict(X_test)

همون طور که مشاهده میکنین شاخص R-squared برای مدل حدود 74 درصد به دست اومده و به این معنیه که قدرت پیش بینی مدل ما 74 درصد و به عبارت علمی تر 74 درصد واریانس موجود در قیمت رو تبیین میکنه.

یکی دیگه از معیارهای سنجش صحت مدل، نرمال بودن توزیع خطای مدل(residuals) هست. به این صورت که خطای مدل نسبتا مختصر و دارای توزیع نرمال باشه. از این بابت هم مدل ما وضعیت قابل قبولی داره

شکل زیر کمک میکنه تصویر واضح تری از مدل پیدا کنیم به این صورت که محور افقی مساحت ملک(مترمربع) و محور عمودی قیمت ملک(میلیارد تومان) هستن و اینکه نقطه های آبی موارد ثبت شده و نقاط نارنجی پیشبینی های مدل هستن که همپوشانی قابل قبولی دارن.

plt.figure(figsize=(10,5))
plt.scatter(X_test[:,-2:-1],y_test)
plt.scatter(X_test[:,-2:-1],y_pred)
plt.xlabel("area")
plt.ylabel("price")

این مدل صرفا یک مدل ساده و اولیه هست و میتونه با مدل های پیچیده تر رگرسیون مثل lasso و ridge و همین طور سایر رگرسیون ها مثل رگرسیون درخت تصمیم، رگرسیون ماشین بردار پشتیبان، شبکه عصبی و ... بهبود قابل ملاحظه ای پیدا کنه. سعی میکنم دیتاها و مدل رو در github قرار بدم (در صورتی که سایت kilid.com مشکلی با این قضیه نداشته باشه). چون داده ها داخلی و واقعی هستن کار کردن با اونها میتونه جالب باشه. در پایان از وقتی که برای مطالعه گذاشتین ممنونم و منتظر شنیدن نظرات هستم

ایمیل: pooryaganji1368@gmail.com