二手房屋数据分析可视化系统-python
1、前提条件
1、安装Qt Designer
在已经安装好python和pycharm的前提下,安装Qt Designer到指定的路径(路径是自己选的):
链接: https://pan.baidu.com/s/12zwqM5i5rQvq_N29RiQ3Sw
提取码: 2pu7
2、安装PyUCI
1、安装PyUCI需要注意设置环境变量,否则会报错。设置的环境变量如下:
2、在pycharm中安装PyUCI,注意参数的配置:
4、配置完成
3、参数设置Arguments
-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py
2、程序目录结构
3、程序代码
1、house_ananlysis.py文件
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.svm import LinearSVR
import re #正则
##忽略警告
import warnings
warnings.filterwarnings('ignore')
plt.rcParams['font.family'] = ['SimHei'] #设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False #解决保存图像时负号“-”显示为方块的问题
house=pd.read_csv('E:/新建文件夹/实训/项目/二手房数据.csv',encoding='gbk')
###查看是否有空缺值
print("查看空缺值:\n")
print(house.info())##可以看出只有电梯那一列有空缺值
house['电梯'].fillna('未知', inplace=True)###填充数据
###再次进行查看是否有空缺值
print("再次进行查看是否有空缺值:\n")
print(house.info())###确认数据没有空缺值
print("可以看到每一列都没有空缺值:\n")
print(house.isnull().any())##可以看到每一列都没有空缺值
##获取各市区二手房均价
def get_average_price():
group=house.groupby('市区')
averge_price_group=group['价格(万元)'].mean()
##获取区域
region=averge_price_group.index
#区域对应均价格
averge_price=averge_price_group.values.astype(int)
return region,averge_price#返回区域及对应均价格
#各区房子数量比列
def get_house_number():
group_number=house.groupby('市区').size()
region=group_number.index#区域
numbers=group_number.values
percentage=numbers/numbers.sum()*100
return region,percentage#返回区域和百分比
#全市二手房屋装修程度分析
##获取全市二手房屋装修程度对比
def get_renovation():
group_renovation=house.groupby('装修情况').size()
type=group_renovation.index
numbers=group_renovation.values
return type,numbers
#前5个热门户型均价分析
##获取二手房热门户型均价
def get_house_type():
house_type_number=house.groupby('户型').size()
sort_values=house_type_number.sort_values(ascending=False)#将户型分组数量按照降序排序
top_five=sort_values.head(5)#提取前5个热门户型
house_type_price=house.groupby('户型')['价格(万元)'].mean()#获取每个户型均价价格
type=house_type_price[top_five.index].index ##获取前五个户型
price=house_type_price[top_five.index].values ##获取前五个户型均价价格
return type,price.astype(int)
#二手房屋售价预测----使用户型和面积进行未来房价的预测
print("查看户型中包含的不同数据:\n",house['户型'].unique())
# 1、因为含文字信息并不能实现数据分析的拟合工作,所以这里将户型中的数据进行了独立字段的处理
def parse_house_type(house_type):
# 优先匹配包含室和厅的完整格式
full_match = re.search(r'(\d+)室(\d+)厅', house_type)
if full_match:
rooms = int(full_match.group(1))
halls = int(full_match.group(2))
# 如果没有找到完整格式,则分别尝试匹配室和厅
elif '室' in house_type:
room_match = re.search(r'(\d+)室', house_type)
rooms = int(room_match.group(1)) if room_match else float('nan')
halls = float('nan') # 如果没有厅的信息,则设置为NaN
else:
# 如果既没有室也没有厅的信息,则都设置为NaN(或者你可以根据需求设置为其他值)
rooms = float('nan')
halls = float('nan')
return rooms, halls
# 重新应用这个函数到'户型'列
house[['室', '厅']] = house['户型'].apply(parse_house_type).apply(pd.Series)
##获取价格预测
def get_price_predict():
house_copy = house.copy() # 复制数据
#2、因为只是使用户型和面积来进行未来房价的预测,所以这里需删除无意义的数据
del house_copy['市区']
del house_copy['小区']
##因为户型已经进行了独立字段的处理,所以这里需要将其进行删除处理
del house_copy['户型']
del house_copy['朝向']
del house_copy['楼层']
del house_copy['装修情况']
del house_copy['电梯']
del house_copy['年份']
'''
删除house_copy数据中存在的空值,虽然在数据清洗的时候已经进行了处理,
但这里为了保证数据预测的准确性,将其进行了处理
'''
house_copy.dropna(axis=0,how='any',inplace=True)
#3、将面积小于300平方米的数据筛选出来
new_data=house_copy[house_copy['面积(㎡)']<300]
print("面积小于30平方米的数据前五个:\n",new_data.head())
#4、添加自定义预测数据,并将数据进行标准化,定义特征数据和目标数据,最后训练回归模型进行未知房价的预测
new_data.loc[23676]=[88.0,None,2.0,1.0]
new_data.loc[23677]=[136.0,None,3.0,2.0]
data_train=new_data.loc[0:23675]
x_list=['面积(㎡)','室','厅']
data_mean=data_train.mean()#均值
data_std=data_train.std()#方差
data_train=(data_train-data_mean)/data_std#数据标准化
x_train=data_train[x_list].values#特征数据
y_train=data_train['价格(万元)']#目标数据
linearsvr=LinearSVR(C=0.1)#创建LinearSVR对象
linearsvr.fit(x_train,y_train)#训练模型
#标准化特征数据
x=((new_data[x_list]-data_mean[x_list])/data_std[x_list]).values
#添加预测房价的信息列
new_data['y_predict']=linearsvr.predict(x) * data_std['价格(万元)']+data_mean['价格(万元)']
print('真实值与预测值分别为:\n',new_data[['价格(万元)','y_predict']])
y = new_data['价格(万元)'].loc[23658:] # 获取23658之后的真实数据
y_predict = new_data['y_predict'].loc[23658:]
return y,y_predict.astype(int)
2、chart.py文件
import matplotlib
import matplotlib.pyplot as plt
#避免中文乱码
matplotlib.rcParams['font.sans-serif']=['SimHei']
matplotlib.rcParams['axes.unicode_minus']=False
#饼图显示
def pie_chart(size,label,title):
plt.figure()#设置画布
#设置各部分大小、各部分标签、标签文本距圆心的位置、圆里面文本的位置、是否显示阴影
#startangle起始角度,默认为0从逆时针旋转;设置圆内文本距圆心距离
plt.pie(size,labels=label,labeldistance=1.05,autopct="%1.1f%%",shadow=False,startangle=0,
pctdistance=0.6)
plt.axis("equal")#设置横轴和纵轴大小相等
plt.title(title,fontsize=12)#设置标题,字体大小
plt.legend(bbox_to_anchor=(0.03,1))#让图列生效,并设置图列显示位置
plt.show()
#显示预测房价折线图
def line_predict(y,y_predict,title):
plt.figure()
plt.plot(y,color='r',marker='o',label='真实房价')
plt.plot(y_predict,color='b',marker='*',label='预测房价')
plt.xlabel('所预测数据位置索引')
plt.ylabel('房子价格(万元)')
plt.title(title)
plt.legend()
plt.grid()
plt.show()
#均价条形图
def averge_price_bar(x,y,title):
plt.figure()
#x各区域的数据,y为各区域的均价数据
plt.bar(x,y,alpha=0.8)
plt.xlabel("区域")
plt.ylabel("均价")
plt.title(title)
for x,y in enumerate(y):
plt.text(x,y+100,y,ha='center')
plt.show()
#显示装修条形图
def renovation_bar(x,y,title):
plt.figure()
# x为装修类型,y为每种装修类型对应的数量
plt.bar(x, y, alpha=0.8)
plt.xlabel("装修类型")
plt.ylabel("数量")
plt.title(title)
for x, y in enumerate(y):
plt.text(x, y + 10, y, ha='center')
plt.show()
#显示热门户型的水平条形图
def hot_house_barh(price,type,title):
plt.figure()
# price为热门户型的均价,type为热门户型的名称
plt.barh(type,price,height=0.3,color='r',alpha=0.8)
plt.xlim(0,1500)
plt.xlabel("均价")
plt.title(title)
for y, x in enumerate(price):
plt.text(x+10, y, str(x)+'万元', va='center')
plt.show()
3、show_window.py文件
from PyQt5.QtWidgets import QMainWindow,QApplication #Qt中必备类
from img.MainWindow import Ui_MainWindow #导入主窗体文件中的ui类
import sys #导入系统模块
import house_ananlysis #导入自定义二手房数据分析模块
import chart #导入自定义绘图模块
#主窗体初始化类
class Main(QMainWindow,Ui_MainWindow):
def __init__(self):
super(Main,self).__init__()
self.setupUi(self)
#显示各区二手房均价分析图
def show_average_price(self):
#获取分析后的房子区域与均价价格
region,average_price=house_ananlysis.get_average_price()
chart.averge_price_bar(region,average_price,'各区二手房均价分析')
#显示各区二手房数量所占比列
def show_house_number(self):
#获取房屋区域与数量的百分比
region,percentage=house_ananlysis.get_house_number()
chart.pie_chart(percentage,region,'各区二手房数量所占比列')#显示图表
#显示全市二手房装修程度分析
def show_renovation(self):
type,numbers=house_ananlysis.get_renovation()#获取全市二手房装修类型及数量
chart.renovation_bar(type,numbers,'全市二手房屋装修程度分析')
#显示前五热门户型均价分析
def show_type(self):
type,price=house_ananlysis.get_house_type()#户型及户型均价
chart.hot_house_barh(price,type,'前五热门户型均价分析')
#显示二手房屋售价预测折线图
def show_total_price(self):
true_price,predict_price=house_ananlysis.get_price_predict()#获取真实价格及预测价格
chart.line_predict(true_price,predict_price,'二手房屋价格预测折线图')
if __name__ =='__main__':
app=QApplication(sys.argv) #app对象
main=Main() #主窗体对象
#显示分析图,按钮事件
main.btn_1.triggered.connect(main.show_average_price)
main.btn_2.triggered.connect(main.show_house_number)
main.btn_3.triggered.connect(main.show_renovation)
main.btn_4.triggered.connect(main.show_type)
main.btn_5.triggered.connect(main.show_total_price)
main.show()#显示主窗体
sys.exit(app.exec_())#当窗口创建完成,需结束主循环
4、MainWindow.py文件
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(703, 390)
MainWindow.setMinimumSize(QtCore.QSize(695, 390))
MainWindow.setMaximumSize(QtCore.QSize(710, 695))
MainWindow.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(0, 0, 711, 321))
self.label.setText("")
self.label.setPixmap(QtGui.QPixmap("img/background.png"))
self.label.setScaledContents(True)
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.toolBar = QtWidgets.QToolBar(MainWindow)
self.toolBar.setAcceptDrops(True)
self.toolBar.setIconSize(QtCore.QSize(37, 25))
self.toolBar.setObjectName("toolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
self.btn_1 = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("img/btn_1.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_1.setIcon(icon)
font = QtGui.QFont()
font.setPointSize(7)
self.btn_1.setFont(font)
self.btn_1.setObjectName("btn_1")
self.btn_2 = QtWidgets.QAction(MainWindow)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap("img/btn_2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_2.setIcon(icon1)
font = QtGui.QFont()
font.setPointSize(7)
self.btn_2.setFont(font)
self.btn_2.setObjectName("btn_2")
self.btn_3 = QtWidgets.QAction(MainWindow)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap("img/btn_3.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_3.setIcon(icon2)
font = QtGui.QFont()
font.setPointSize(7)
self.btn_3.setFont(font)
self.btn_3.setObjectName("btn_3")
self.btn_4 = QtWidgets.QAction(MainWindow)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap("img/btn_4.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_4.setIcon(icon3)
font = QtGui.QFont()
font.setPointSize(7)
self.btn_4.setFont(font)
self.btn_4.setObjectName("btn_4")
self.btn_5 = QtWidgets.QAction(MainWindow)
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap("img/btn_5.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_5.setIcon(icon4)
font = QtGui.QFont()
font.setPointSize(7)
self.btn_5.setFont(font)
self.btn_5.setObjectName("btn_5")
self.toolBar.addSeparator()
self.toolBar.addAction(self.btn_1)
self.toolBar.addSeparator()
self.toolBar.addAction(self.btn_2)
self.toolBar.addSeparator()
self.toolBar.addAction(self.btn_3)
self.toolBar.addSeparator()
self.toolBar.addAction(self.btn_4)
self.toolBar.addSeparator()
self.toolBar.addAction(self.btn_5)
self.toolBar.addSeparator()
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "二手房屋数据分析可视化系统"))
self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
self.btn_1.setText(_translate("MainWindow", "各区二手房均价分析"))
self.btn_1.setToolTip(_translate("MainWindow", "各区二手房均价分析"))
self.btn_2.setText(_translate("MainWindow", "各区二手房数量所占比例"))
self.btn_2.setToolTip(_translate("MainWindow", "各区二手房数量所占比例"))
self.btn_3.setText(_translate("MainWindow", "全市二手房装修程度分析"))
self.btn_3.setToolTip(_translate("MainWindow", "全市二手房装修程度分析"))
self.btn_4.setText(_translate("MainWindow", "热门户型均价分析"))
self.btn_4.setToolTip(_translate("MainWindow", "热门户型均价分析"))
self.btn_5.setText(_translate("MainWindow", "二手房售价预测"))
self.btn_5.setToolTip(_translate("MainWindow", "二手房售价预测"))
4、程序运行结果
5、源码提取,已打包
链接: https://pan.baidu.com/s/1CcUmcBR9yvhNHCDkustr7A
提取码: aw48
6、提示
扩展名为.ui的文件,可通过如下方式采用PyUCI进行解析,如MainWindow.ui文件解析成MainWindow.py文件
7、所采用的数据
链接:https://pan.baidu.com/s/1QSiS0Is57nZmRVUhiDwKtg
提取码:yyss