در این مطلب به بررسی و تحلیل وضعیت املاک بر اساس آگهیهای ثبت شده برای فروش و اجاره املاک میپردازیم. این تحلیل براساس دادههای جمعآوری شده در طول یک هفته برای املاک شهر اصفهان انجام شده است.
دادههای جمعآوری شده پس از پاکسازی به کمک کتابخانههای تحلیلی موجود در زبان برنامهنویسی پایتون تحلیل شدهاند. این کتابخانهها در زیر آمدهاند.
import pandas as pd import numpy as np import seaborn as sns import matplotlib import matplotlib.pyplot as plt import matplotlib.font_manager as fm from mpl_toolkits.mplot3d import Axes3D from sklearn.cluster import KMeans from sklearn.preprocessing import MinMaxScaler from persiantext import PersianText
بخشی از تحلیل روی همه املاک و بخشی هم روی املاک فروشی و اجارهای بصورت جداگانه انجام شده است.
df2 = pd.read_csv('isf-realestate.csv') df_sell = df2[df2['ad_type'] == 'فروشی'].copy() del df_sell['mortgage'] del df_sell['rent'] df_sell = df_sell.dropna() df_rent = df2[df2['ad_type'] == 'اجاره'].copy() del df_rent['sell_price'] del df_rent['sell_unit_price'] df_rent = df_rent.dropna() df_sell_apartment = df_sell[df_sell['sub_category'] == 'آپارتمان']
همانگونه که مشاهده میشود بخش عمدهای از آگهیها مربوط به فروش املاک میشود.
df_agg = df2[['ad_type', 'sub_category']].groupby(by=['ad_type']).count() df_agg = df_agg.reset_index() df_agg['ad_type'] = df_agg['ad_type'].apply(lambda x: PersianText.reshape(x)) df_agg.columns = [PersianText.reshape(c) for c in list(df_agg.columns)] df_agg = df_agg.fillna(0) plt.subplots(figsize=(15, 10)) plt.pie(x=df_agg['sub_category'], autopct='%1.1f%%', pctdistance=0.5, shadow=True, textprops={'fontsize':20}, labels=df_agg['ad_type']) plt.title(PersianText.reshape('نوع آگهی'), fontdict={'fontsize':20}) plt.legend(list(df_agg['ad_type']), fontsize=15) plt.show()

از سوی دیگر مشاهده میشود که بیشترین آگهیها مربوط به فروش و اجاره «آپارتمان» میشود.
aggregate = df2.groupby(by=['sub_category']).count()['age'].nlargest(4) labels = list(aggregate.index) labels = [PersianText.reshape(s) for s in labels] explode = (0.2, 0, 0, 0) fig1, ax1 = plt.subplots() fig1.set_size_inches(10, 7) ax1.pie(aggregate, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True, startangle=0, textprops={'fontsize':15}) ax1.axis('equal') plt.title(PersianText.reshape('نمای کلی'), fontdict={'fontsize':20}) plt.show()

در تفکیک املاک فروشی و اجارهای هم آگهیهای «آپارتمان» بیشترین تعداد را دارد.
df_agg = df2[['ad_type', 'sub_category', 'age']].groupby(by=['ad_type', 'sub_category']).count() df_agg = df_agg.unstack().reset_index() df_agg['ad_type'] = df_agg['ad_type'].apply(lambda x: PersianText.reshape(x)) df_agg = df_agg.set_index('ad_type') df_agg.columns = [PersianText.reshape(c) for c in list(df_agg.columns.droplevel(0))] df_agg = df_agg.fillna(0) plt.subplots(figsize=(15, 10)) # plt.pie(x=df_agg.iloc[0,:], autopct='%1.1f%%', pctdistance=0.5, shadow=True, textprops={'fontsize':12}) # plt.title(PersianText.reshape('املاک اجارهای'), fontdict={'fontsize':20}) # plt.legend(list(df_agg.columns), fontsize=15) plt.pie(x=df_agg.iloc[1,:], autopct='%1.1f%%', pctdistance=0.5, shadow=True, textprops={'fontsize':12}) plt.title(PersianText.reshape('املاک فروشی'), fontdict={'fontsize':20}) plt.legend(list(df_agg.columns), fontsize=15) plt.show()


در مقایسه وضعیت «تعداد اتاق» به «مساحت» املاک فروشی مشاهده میشود که بیشترین تعداد آگهی مربوط به املاک دو اتاقه با متراژ کمتر از ۲۰۰ متر است.
df_temp = df_sell[df_sell['sell_price'] <= 3000000000] # xlabel = PersianText.reshape('تعداد اتاق') # ylabel = PersianText.reshape('مساحت') # sns.jointplot(x='rooms', y='area', data=df_temp, ylim=(0, 600), kind='kde', height=8) \ # .set_axis_labels(xlabel, ylabel) xlabel = PersianText.reshape('مساحت') ylabel = PersianText.reshape('قیمت') sns.jointplot(x='area', y='sell_price', data=df_temp, xlim=(0, 600), kind='kde', height=8) \ .set_axis_labels(xlabel, ylabel) plt.show()

از سوی دیگر مقایسه «مساحت» و «قیمت» در املاک فروشی نشان میدهد که بیشترین تعداد آگهی مربوط به املاک زیر ۲۰۰ متر با محدوده قیمتی بین ۵۰۰ میلیون تومان تا یک میلیارد تومان است.

نمودار زیر نشان میدهد که در بین املاک فروشی بیشترین تعداد و بیشترین تنوع قیمت مربوط به آپارتمانها میشود.
df_temp = df_sell[df_sell['sell_price'] <= 3000000000] plt.subplots(figsize=(15, 10)) ax = sns.swarmplot(x='sub_category', y='sell_price', data=df_temp, size=4) ax.set_title(PersianText.reshape('محدوده قیمت املاک فروشی در دستههای گوناگون'), fontsize=25) ax.set_xlabel(PersianText.reshape('دستهبندی'), fontsize=20) ax.set_ylabel(PersianText.reshape('قیمت'), fontsize=20) reshape_axes_labels(ax) plt.show()

علاوه بر این بیشترین آپارتمانهای فروشی دارای دو اتاق خواب هستند و بیشتر آنها در محدود قیمتی ۵۰۰ میلیون تا یک میلیارد تومان قرار دارند.

در بین املاک کمتر از سه میلیارد تومان، دسته «دفتر کار، اتاق اداری و مطب» محدوه قیمتی بزرگتری نسبت به سایر دستهها دارد.
plt.subplots(figsize=(15, 10)) df_temp = df_sell[df_sell['sell_price'] <= 3000000000] ax = sns.boxplot(x='sub_category', y='sell_price', data=df_temp) ax.set_title(PersianText.reshape('محدوده قیمت املاک فروشی در دستههای گوناگون'), fontsize=25) ax.set_xlabel(PersianText.reshape('دستهبندی'), fontsize=20) ax.set_ylabel(PersianText.reshape('قیمت'), fontsize=20) reshape_axes_labels(ax) plt.show()

نمودار زیر نشان دهنده تعداد آگهیهای فروش در محلها و مناطق مختلف شهر است.
plt.subplots(figsize=(20, 15)) ax = sns.countplot(x='location', data=df_sell) ax.set_title(PersianText.reshape('تعداد املاک فروشی در مناطق شهر'), fontsize=25) ax.set_xlabel(PersianText.reshape('محل'), fontsize=20) ax.set_ylabel(PersianText.reshape('تعداد'), fontsize=20) reshape_axes_labels(ax) plt.xticks(rotation=90, fontsize=15) plt.show()

محدوده قیمتی آپارتمانهای فروشی در مناطق مختلف شهر در نمودار زیر آمده است.
df_temp = df_sell_apartment[df_sell_apartment['sell_price'] <= 5e9] plt.subplots(figsize=(15, 10)) ax = sns.boxplot(x='location', y='sell_price', data=df_temp) ax.set_title(PersianText.reshape('محدوده قیمت آپارتمانهای فروشی در محلهای شهر'), fontsize=25) ax.set_xlabel(PersianText.reshape('محل'), fontsize=20) ax.set_ylabel(PersianText.reshape('قیمت'), fontsize=20) reshape_axes_labels(ax) plt.xticks(rotation=90, fontsize=15) plt.show()

خوشهبندی
یک خوشهبندی چهارتایی بر اساس «محل»، «سن ملک»، «متراژ» و «قیمت فروش» روی آپارتمانهای فروشی پیادهسازی شد که نتیجه آن در نمودار زیر آمده است.
همانگونه که از شکل پیداست دو خوشه بطور کامل تفکیک شدهاند یکی مربوط به آپارتمانهای محلی مشخص و دیگری مربوط به آپارتمانهای با متراژ تقریبا بالای ۱۵۰ متر و قیمت تقریبا بالای یک میلیارد تومان. اما دو خوشه دیگر که مربوط به آپارتمانهای زیر ۱۵۰ متر و زیر یک میلیارد هستند در شکل قابل تفکیک نیستند و احتمالا پارامتر سن ملک در آنها دخیل است.
df_temp = df_sell_apartment[(df_sell_apartment['sell_price'] <= 5e9) & (df_sell_apartment['area'] <= 250)].copy() loc_weights = df_temp['location'].value_counts() df_temp['location_weight'] = df_temp['location'].apply(lambda x: loc_weights[x]) cols = ['location_weight', 'age', 'area', 'sell_price'] scaler = MinMaxScaler() scaled_data = scaler.fit_transform(df_temp[cols].values.astype(np.float)) km = KMeans(4) clusters = km.fit_predict(scaled_data) df_clusters = df_temp.copy() df_clusters['cluster'] = clusters
fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111, projection='3d') xs = df_clusters['sell_price'].values.astype(np.float) ys = df_clusters['area'].values.astype(np.float) zs = df_clusters['location_weight'].values.astype(np.float) types = df_clusters['cluster'].values ax.scatter(xs, ys, zs, c=types, cmap='viridis') #, marker='o') ax.set_title(PersianText.reshape('خوشهبندی آپارتمانهای فروشی'), fontsize=25) ax.set_xlabel(PersianText.reshape('قیمت'), fontsize=15) ax.set_ylabel(PersianText.reshape('مساحت'), fontsize=15) ax.set_zlabel(PersianText.reshape('محل'), fontsize=15) ax.view_init(60, -60) plt.show()

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