初学者也能懂!用Python做房屋销售数据分析,从0到1上手实战
大家好!今天带大家做一个超实用的数据分析小demo——房屋销售数据分析。不管你是刚学Python的新手,还是想入门数据分析的同学,跟着这篇文章走,你不仅能看懂代码,还能亲手跑出属于自己的分析结果,甚至能从数据里挖出关于房价的小秘密~
一、先搞懂:我们要做什么?用什么做?
1. 目标
我们有一份房屋销售的CSV数据(比如包含房屋面积、卧室数、价格、销售日期等信息),要通过Python完成:
- 加载数据并看看数据长啥样(有没有问题)
- 清理数据(补漏洞、加新信息)
- 画图表看规律(比如房价分布、哪个区房子贵)
- 分析影响房价的因素(面积?卧室数?)
- 看销售趋势(哪个月卖得多?)
2. 用到的“工具库”
就像做饭需要锅碗瓢盆,数据分析也需要专门的Python库,我们这次用4个核心库:
库名 | 作用 | 通俗理解 |
---|---|---|
pandas | 数据处理(读数据、算统计) | 数据的“记事本+计算器” |
numpy | 数值计算(帮我们算模型) | 更强大的“计算器” |
matplotlib | 画图表(直方图、散点图) | 数据的“画图板” |
seaborn | 美化图表(比如热力图) | 图表的“化妆师” |
二、第一步:环境准备(新手必看)
在写代码前,得先把“工具”装好。打开你的Python编辑器(比如PyCharm、VS Code,没有的同学可以百度下载一下就行),有python环境后,先执行下面的命令安装需要的库:
pip install pandas numpy matplotlib seaborn
安装完成后,我们先写一段“准备代码”,避免后续出小问题(比如图表中文乱码):
# 导入所有需要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import os
# 关键!设置中文字体(不然图表里的中文会变成乱码方框)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用“黑体”显示中文
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
三、第二步:加载数据,先“摸透”数据长啥样
拿到数据第一步,不是直接分析,而是先看看数据“健康”吗?有多少行多少列?有没有缺数据?这一步我们写个load_and_explore_data()
函数来搞定。
1. 代码拆解:加载数据并检查
def load_and_explore_data():
print("=== 房屋销售数据分析案例 ===\n")
# 1. 先确认数据文件在不在
csv_file = 'house_sales_data.csv' # 你的数据文件名
if not os.path.exists(csv_file):
print(f"错误: 找不到数据文件 {csv_file}")
print("请准备这样的CSV文件,必须包含这些列:")
print("house_id(房屋ID), area(面积), bedrooms(卧室数), bathrooms(卫生间数),")
print("location(区域), age(房龄), price(价格), sale_date(销售日期), sale_status(销售状态)")
return None # 文件不在就退出,避免报错
# 2. 读取CSV数据(pandas的核心功能!)
try:
df = pd.read_csv(csv_file) # df是“DataFrame”,像Excel表格一样的结构
# 把“销售日期”转成日期格式(方便后续按日期分析)
if 'sale_date' in df.columns:
df['sale_date'] = pd.to_datetime(df['sale_date'])
# 3. 打印数据概览,让我们“眼见为实”
print("1. 数据概览:")
print(f"数据集形状: {df.shape}") # (行数, 列数),比如(1000,9)就是1000条数据,9个字段
print("\n前5行数据(看看长啥样):")
print(df.head()) # 显示前5行,避免数据太多看不过来
print("\n2. 数据基本信息(有没有缺失值、数据类型):")
print(df.info()) # 重点看“Non-Null Count”,如果比总行数少,就是有缺失值
print("\n3. 数值型数据统计(平均值、最大值这些):")
print(df.describe()) # 只对数字列生效,比如面积的平均值、房价的最大值
print("\n4. 分类数据统计(比如哪个区房子多):")
if 'location' in df.columns:
print("各区房屋数量:")
print(df['location'].value_counts()) # 统计每个区域有多少套房子
if 'sale_status' in df.columns:
print("\n销售状态统计(比如已售/待售):")
print(df['sale_status'].value_counts())
return df # 返回清洗好的“表格”,给后续步骤用
except Exception as e:
print(f"读文件出错了: {e}") # 万一格式错了,告诉我们哪里错了
return None
2. 新手必问:这步能得到什么?
举个例子,如果你的数据有1000条房屋记录,运行后会看到:
- 数据集形状:
(1000, 9)
(1000行数据,9列信息) - 前5行能看到具体数据,比如某套房子面积120㎡,3个卧室,价格200万
- 从
df.info()
能发现:比如“age(房龄)”列有10个缺失值(需要后续处理) - 从
df.describe()
能看到:房价平均180万,最高500万,最低80万 - 从区域统计能看到:“城东”区房子最多(300套),“城西”最少(150套)
四、第三步:数据清洗——“修bug”的关键一步
拿到的数据很少是“完美”的,比如有缺失值、重复值,或者需要加一些新信息(比如“每平米单价”)。这一步我们用clean_data()
函数搞定。
1. 代码拆解:清洗数据
def clean_data(df):
print("\n=== 数据清洗 ===")
# 1. 检查缺失值(数据里的“空格子”)
print("缺失值检查(每列有多少空值):")
print(df.isnull().sum()) # 比如age列有10个空值,这里就会显示10
# 2. 检查重复值(完全一样的行,可能是录入错误)
print(f"\n重复值数量: {df.duplicated().sum()}") # 比如有5个重复行
# 3. 新增有用的特征(让数据更有分析价值)
# 新增“每平米单价”:总价/面积(买房时最关心的指标之一)
if 'price' in df.columns and 'area' in df.columns:
df['price_per_sqm'] = df['price'] / df['area'] # 自动新增一列
# 新增“月份”“季度”:方便按时间分析(比如3月卖了多少套)
if 'sale_date' in df.columns:
df['month'] = df['sale_date'].dt.month # 提取月份(1-12)
df['quarter'] = df['sale_date'].dt.quarter # 提取季度(1-4)
# (新手拓展:如果有缺失值,怎么处理?)
# 比如用“房龄的平均值”填充age列的空值:df['age'].fillna(df['age'].mean(), inplace=True)
# 比如删除重复值:df.drop_duplicates(inplace=True)
print("\n新增特征后的数据(看最后3列):")
print(df.head()) # 会看到多了price_per_sqm、month、quarter三列
return df
2. 为什么要做数据清洗?
- 缺失值会导致后续画图或建模报错(比如算平均房价时,空值会让结果不准)
- 重复值会让数据“虚高”(比如1条数据重复5次,会误以为有5套房子)
- 新增特征能帮我们挖掘更多信息:比如“每平米单价”能直接对比不同区域的房价高低,比总价更直观
五、第四步:探索性数据分析——画图看规律!
数据分析的核心是“可视化”——用图表代替枯燥的数字,一眼看出规律。这一步exploratory_analysis()
函数会生成2张综合图表,包含4个关键分析。
1. 代码拆解:画图表找规律
def exploratory_analysis(df):
print("\n=== 探索性数据分析 ===")
# 1. 画第一张图:包含4个子图(价格分布、面积分布、各区均价、面积vs价格)
plt.figure(figsize=(15, 10)) # 设置图的大小(宽15,高10)
# 子图1:房屋价格分布(直方图)
plt.subplot(2, 2, 1) # 2行2列的第1个位置
plt.hist(df['price'], bins=20, alpha=0.7, color='skyblue', edgecolor='black')
plt.title('房屋价格分布') # 标题
plt.xlabel('价格(元)') # X轴标签
plt.ylabel('频数') # Y轴标签(有多少套房子在这个价格区间)
# 子图2:房屋面积分布(直方图)
plt.subplot(2, 2, 2) # 2行2列的第2个位置
plt.hist(df['area'], bins=15, alpha=0.7, color='lightgreen', edgecolor='black')
plt.title('房屋面积分布')
plt.xlabel('面积(平方米)')
plt.ylabel('频数')
# 子图3:各区平均价格(柱状图)
plt.subplot(2, 2, 3) # 2行2列的第3个位置
avg_price_by_location = df.groupby('location')['price'].mean().sort_values() # 按区域算均价并排序
avg_price_by_location.plot(kind='bar', color='orange', alpha=0.7)
plt.title('各区平均房屋价格')
plt.xlabel('区域')
plt.ylabel('平均价格(元)')
plt.xticks(rotation=45) # 区域名旋转45度,避免重叠
# 子图4:面积与价格的关系(散点图)
plt.subplot(2, 2, 4) # 2行2列的第4个位置
plt.scatter(df['area'], df['price'], alpha=0.6, color='purple') # 每个点代表一套房子
plt.title('房屋面积与价格关系')
plt.xlabel('面积(平方米)')
plt.ylabel('价格(元)')
plt.tight_layout() # 自动调整子图位置,避免重叠
plt.savefig('house_sales_analysis1.png', dpi=300, bbox_inches='tight') # 保存图片(高清)
plt.show() # 显示图片
# 2. 画第二张图:卧室数量影响、月度销售情况
plt.figure(figsize=(12, 5))
# 子图1:卧室数量对均价的影响(柱状图)
plt.subplot(1, 2, 1) # 1行2列的第1个位置
avg_price_by_bedrooms = df.groupby('bedrooms')['price'].mean() # 按卧室数算均价
avg_price_by_bedrooms.plot(kind='bar', color='lightcoral', alpha=0.7)
plt.title('卧室数量对平均价格的影响')
plt.xlabel('卧室数量')
plt.ylabel('平均价格(元)')
plt.xticks(rotation=0) # 卧室数少,不用旋转
# 子图2:每月销售数量(折线图)
plt.subplot(1, 2, 2) # 1行2列的第2个位置
sales_by_month = df.groupby('month').size() # 按月份统计销售套数
sales_by_month.plot(kind='line', marker='o', color='blue', linewidth=2) # 折线图+圆点标记
plt.title('每月房屋销售数量')
plt.xlabel('月份')
plt.ylabel('销售数量')
plt.xticks(range(1, 13)) # X轴显示1-12月
plt.tight_layout()
plt.savefig('house_sales_analysis2.png', dpi=300, bbox_inches='tight')
plt.show()
2. 这张图能告诉我们什么?(新手必看)
举个实际分析结果的例子:
- 价格分布:大部分房子价格在150-250万之间(直方图的“山峰”在这个区间),只有少数豪宅超过400万
- 面积分布:面积集中在90-130㎡(刚需户型为主),180㎡以上的大户型很少
- 各区均价:“城南”区均价最高(2.5万/㎡),“城北”最低(1.8万/㎡)(柱状图从低到高排,一眼看清)
- 面积与价格:散点图呈“斜向上”的趋势——面积越大,价格越高(正相关)
- 卧室数量影响:4卧室房子均价(280万)> 3卧室(200万)> 2卧室(150万)(卧室越多越贵)
- 月度销售:3月和9月销售高峰(可能是金三银九),1月销售最少(春节前后)
六、第五步:深入分析——找影响房价的关键因素
光看表面规律还不够,我们还要用“数据说话”:哪些因素对房价影响最大?用简单的机器学习模型(线性回归)来分析。
1. 代码拆解:深入分析(含机器学习入门)
def advanced_analysis(df):
print("\n=== 深入分析 ===")
# 1. 计算相关系数(看变量之间的“关系紧密程度”)
numeric_cols = ['area', 'bedrooms', 'bathrooms', 'age', 'price', 'price_per_sqm'] # 数值型变量
correlation_matrix = df[numeric_cols].corr() # 生成相关系数矩阵
print("数值变量相关系数矩阵(越接近1,关系越紧密):")
print(correlation_matrix.round(2)) # 保留2位小数,更易读
# 画相关系数热力图(更直观)
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0,
square=True, fmt='.2f', cbar_kws={'shrink': .8})
plt.title('变量间相关系数热力图')
plt.tight_layout()
plt.savefig('correlation_heatmap.png', dpi=300, bbox_inches='tight')
plt.show()
# 2. 各区每平米均价分析(比总价更公平)
print("\n各区每平米均价(含标准差和数量):")
price_per_sqm_by_location = df.groupby('location')['price_per_sqm'].agg(['mean', 'std', 'count'])
# mean=均价,std=标准差(价格波动大小),count=房子数量
print(price_per_sqm_by_location.round(2))
# 3. 简单房价预测模型(线性回归)
from sklearn.linear_model import LinearRegression # 导入线性回归模型
from sklearn.model_selection import train_test_split # 拆分训练/测试数据
from sklearn.metrics import mean_squared_error, r2_score # 模型评估指标
# 选择“特征”(用来预测的因素)和“目标”(要预测的结果)
X = df[['area', 'bedrooms', 'bathrooms', 'age']] # 特征:面积、卧室数、卫生间数、房龄
y = df['price'] # 目标:房价
# 拆分数据:80%用来训练模型,20%用来测试模型准不准
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 训练模型(让电脑从数据里学规律)
model = LinearRegression()
model.fit(X_train, y_train)
# 用模型预测测试集的房价
y_pred = model.predict(X_test)
# 评估模型(看预测得准不准)
print(f"\n模型评估结果:")
print(f"R²分数: {r2_score(y_test, y_pred):.3f}") # 越接近1,预测越准(0.7以上算不错)
print(f"均方根误差(RMSE): {np.sqrt(mean_squared_error(y_test, y_pred)):.2f}") # 平均误差(越小越好)
# 分析“特征重要性”(哪个因素对房价影响最大)
feature_importance = pd.DataFrame({
'feature': X.columns, # 特征名(面积、卧室数等)
'coefficient': model.coef_, # 系数(正负代表影响方向,绝对值代表影响大小)
'abs_importance': abs(model.coef_) # 系数绝对值(方便排序)
}).sort_values('abs_importance', ascending=False) # 按重要性从大到小排
print("\n特征重要性(哪个因素对房价影响最大):")
print(feature_importance)
2. 新手能看懂的关键结论
- 相关系数:比如“area(面积)”和“price(房价)”的相关系数是0.85(接近1),说明面积对房价影响极大;“age(房龄)”和“price”相关系数是-0.3(负的),说明房龄越大,房价越低(符合常识)
- 热力图:红色代表正相关(越红越相关),蓝色代表负相关(越蓝越负相关),一眼看出面积和房价最红(关系最铁)
- 每平米均价:“城南”不仅总价高,每平米均价也高(2.5万/㎡),而且标准差小(价格稳定),说明城南房价坚挺
- 模型结果:比如R²=0.75,说明用面积、卧室数等4个特征,能解释75%的房价变化(算不错的模型);RMSE=20万,说明预测房价时,平均误差约20万
- 特征重要性:面积的系数最大(比如10000),说明面积每增加1㎡,房价平均涨1万元;房龄系数是-5000,说明房龄每增加1年,房价平均降5000元
七、第六步:销售趋势分析——看时间规律
最后,我们分析销售的时间趋势,比如每周卖多少套,哪个季度房价最高。
1. 代码拆解:销售趋势
def sales_trend_analysis(df):
print("\n=== 销售趋势分析 ===")
# 新增“周数”列(按年份的周数,1-52周)
df['week'] = df['sale_date'].dt.isocalendar().week
# 画趋势图(2个子图)
plt.figure(figsize=(12, 5))
# 子图1:每周销售趋势(折线图)
plt.subplot(1, 2, 1)
weekly_sales = df.groupby('week').size() # 按周统计销售套数
weekly_sales.plot(kind='line', marker='o', color='green', linewidth=2)
plt.title('每周房屋销售趋势')
plt.xlabel('周数')
plt.ylabel('销售数量')
plt.grid(True, alpha=0.3) # 加网格,方便看数值
# 子图2:各季度平均房价(柱状图)
plt.subplot(1, 2, 2)
quarterly_avg_price = df.groupby('quarter')['price'].mean() # 按季度算均价
quarterly_avg_price.plot(kind='bar', color='lightblue', alpha=0.7)
plt.title('各季度平均房屋价格')
plt.xlabel('季度')
plt.ylabel('平均价格(元)')
plt.xticks(rotation=0)
plt.tight_layout()
plt.savefig('sales_trend_analysis.png', dpi=300, bbox_inches='tight')
plt.show()
2. 趋势结论
比如你可能会发现:
- 每周销售:第10周(3月)和第36周(9月)是销售高峰,第52周(12月底)是低谷
- 季度均价:第2季度(4-6月)和第3季度(7-9月)均价最高,第1季度(1-3月)最低
八、最后一步:把所有功能串起来,一键运行!
前面我们写了很多“小功能”,现在用main()
函数把它们串起来,一键完成整个分析流程:
def main():
try:
# 1. 加载和探索数据
df = load_and_explore_data()
if df is None: # 数据加载失败就退出
return
# 2. 数据清洗
df_clean = clean_data(df)
# 3. 探索性分析
exploratory_analysis(df_clean)
# 4. 深入分析
advanced_analysis(df_clean)
# 5. 销售趋势分析
sales_trend_analysis(df_clean)
# 分析完成!告诉用户生成了哪些文件
print("\n=== 分析完成 ===")
print("已生成4张分析图表:")
print("- house_sales_analysis1.png: 价格/面积分布+各区均价+面积vs价格")
print("- house_sales_analysis2.png: 卧室数量影响+月度销售")
print("- correlation_heatmap.png: 变量相关系数热力图")
print("- sales_trend_analysis.png: 每周销售+季度均价")
# 保存清洗后的数据(方便后续复用)
df_clean.to_csv('cleaned_house_sales_data.csv', index=False, encoding='utf-8-sig')
print("\n清洗后的数据已保存到: cleaned_house_sales_data.csv")
except Exception as e:
print(f"分析过程中出错: {e}")
# 只有运行这个文件时,才执行main()函数
if __name__ == "__main__":
main()
九、源代码获取
代码复制即可运行:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import os
# 设置中文字体显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 数据加载和初步探索
def load_and_explore_data():
print("=== 房屋销售数据分析案例 ===\n")
# 从CSV文件读取数据
csv_file = 'house_sales_data.csv'
if not os.path.exists(csv_file):
print(f"错误: 找不到数据文件 {csv_file}")
print("请确保house_sales_data.csv文件存在于当前目录")
print("文件应包含以下列: house_id, area, bedrooms, bathrooms, location, age, price, sale_date, sale_status")
return None
try:
# 读取CSV文件
df = pd.read_csv(csv_file)
# 转换日期列
if 'sale_date' in df.columns:
df['sale_date'] = pd.to_datetime(df['sale_date'])
print("1. 数据概览:")
print(f"数据集形状: {df.shape}")
print("\n前5行数据:")
print(df.head())
print("\n2. 数据基本信息:")
print(df.info())
print("\n3. 数值型数据描述性统计:")
print(df.describe())
print("\n4. 分类变量统计:")
if 'location' in df.columns:
print("各区房屋数量:")
print(df['location'].value_counts())
if 'sale_status' in df.columns:
print("\n销售状态统计:")
print(df['sale_status'].value_counts())
return df
except Exception as e:
print(f"读取文件时出错: {e}")
return None
# 数据清洗
def clean_data(df):
print("\n=== 数据清洗 ===")
# 检查缺失值
print("缺失值检查:")
print(df.isnull().sum())
# 检查重复值
print(f"\n重复值数量: {df.duplicated().sum()}")
# 添加新特征
if 'price' in df.columns and 'area' in df.columns:
df['price_per_sqm'] = df['price'] / df['area']
if 'sale_date' in df.columns:
df['month'] = df['sale_date'].dt.month
df['quarter'] = df['sale_date'].dt.quarter
print("\n新增特征后的数据:")
print(df.head())
return df
# 探索性数据分析
def exploratory_analysis(df):
print("\n=== 探索性数据分析 ===")
# 1. 价格分布
plt.figure(figsize=(15, 10))
plt.subplot(2, 2, 1)
plt.hist(df['price'], bins=20, alpha=0.7, color='skyblue', edgecolor='black')
plt.title('房屋价格分布')
plt.xlabel('价格(元)')
plt.ylabel('频数')
# 2. 面积分布
plt.subplot(2, 2, 2)
plt.hist(df['area'], bins=15, alpha=0.7, color='lightgreen', edgecolor='black')
plt.title('房屋面积分布')
plt.xlabel('面积(平方米)')
plt.ylabel('频数')
# 3. 各区平均价格
plt.subplot(2, 2, 3)
avg_price_by_location = df.groupby('location')['price'].mean().sort_values()
avg_price_by_location.plot(kind='bar', color='orange', alpha=0.7)
plt.title('各区平均房屋价格')
plt.xlabel('区域')
plt.ylabel('平均价格(元)')
plt.xticks(rotation=45)
# 4. 价格与面积关系
plt.subplot(2, 2, 4)
plt.scatter(df['area'], df['price'], alpha=0.6, color='purple')
plt.title('房屋面积与价格关系')
plt.xlabel('面积(平方米)')
plt.ylabel('价格(元)')
plt.tight_layout()
plt.savefig('house_sales_analysis1.png', dpi=300, bbox_inches='tight')
plt.show()
# 5. 卧室数量对价格的影响
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
avg_price_by_bedrooms = df.groupby('bedrooms')['price'].mean()
avg_price_by_bedrooms.plot(kind='bar', color='lightcoral', alpha=0.7)
plt.title('卧室数量对平均价格的影响')
plt.xlabel('卧室数量')
plt.ylabel('平均价格(元)')
plt.xticks(rotation=0)
# 6. 每月销售情况
plt.subplot(1, 2, 2)
sales_by_month = df.groupby('month').size()
sales_by_month.plot(kind='line', marker='o', color='blue', linewidth=2)
plt.title('每月房屋销售数量')
plt.xlabel('月份')
plt.ylabel('销售数量')
plt.xticks(range(1, 13))
plt.tight_layout()
plt.savefig('house_sales_analysis2.png', dpi=300, bbox_inches='tight')
plt.show()
# 深入分析
def advanced_analysis(df):
print("\n=== 深入分析 ===")
# 1. 相关系数矩阵
numeric_cols = ['area', 'bedrooms', 'bathrooms', 'age', 'price', 'price_per_sqm']
correlation_matrix = df[numeric_cols].corr()
print("数值变量相关系数矩阵:")
print(correlation_matrix.round(2))
# 热力图
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0,
square=True, fmt='.2f', cbar_kws={'shrink': .8})
plt.title('变量间相关系数热力图')
plt.tight_layout()
plt.savefig('correlation_heatmap.png', dpi=300, bbox_inches='tight')
plt.show()
# 2. 单价分析
print("\n各区每平方米均价:")
price_per_sqm_by_location = df.groupby('location')['price_per_sqm'].agg(['mean', 'std', 'count'])
print(price_per_sqm_by_location.round(2))
# 3. 房价预测模型(简单线性回归)
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
# 选择特征和目标变量
X = df[['area', 'bedrooms', 'bathrooms', 'age']]
y = df['price']
# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 训练模型
model = LinearRegression()
model.fit(X_train, y_train)
# 预测和评估
y_pred = model.predict(X_test)
print(f"\n模型评估结果:")
print(f"R²分数: {r2_score(y_test, y_pred):.3f}")
print(f"均方根误差: {np.sqrt(mean_squared_error(y_test, y_pred)):.2f}")
# 特征重要性
feature_importance = pd.DataFrame({
'feature': X.columns,
'coefficient': model.coef_,
'abs_importance': abs(model.coef_)
}).sort_values('abs_importance', ascending=False)
print("\n特征重要性:")
print(feature_importance)
# 销售趋势分析
def sales_trend_analysis(df):
print("\n=== 销售趋势分析 ===")
# 按周统计销售数量
df['week'] = df['sale_date'].dt.isocalendar().week
weekly_sales = df.groupby('week').size()
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
weekly_sales.plot(kind='line', marker='o', color='green', linewidth=2)
plt.title('每周房屋销售趋势')
plt.xlabel('周数')
plt.ylabel('销售数量')
plt.grid(True, alpha=0.3)
# 按季度分析
plt.subplot(1, 2, 2)
quarterly_avg_price = df.groupby('quarter')['price'].mean()
quarterly_avg_price.plot(kind='bar', color='lightblue', alpha=0.7)
plt.title('各季度平均房屋价格')
plt.xlabel('季度')
plt.ylabel('平均价格(元)')
plt.xticks(rotation=0)
plt.tight_layout()
plt.savefig('sales_trend_analysis.png', dpi=300, bbox_inches='tight')
plt.show()
# 主函数
def main():
try:
# 加载和探索数据
df = load_and_explore_data()
# 数据清洗
df_clean = clean_data(df)
# 探索性分析
exploratory_analysis(df_clean)
# 深入分析
advanced_analysis(df_clean)
# 销售趋势分析
sales_trend_analysis(df_clean)
print("\n=== 分析完成 ===")
print("已生成以下分析图表:")
print("- house_sales_analysis1.png: 基础分布分析")
print("- house_sales_analysis2.png: 卧室和月度销售分析")
print("- correlation_heatmap.png: 相关系数热力图")
print("- sales_trend_analysis.png: 销售趋势分析")
# 保存处理后的数据
df_clean.to_csv('cleaned_house_sales_data.csv', index=False, encoding='utf-8-sig')
print("\n清洗后的数据已保存到: cleaned_house_sales_data.csv")
except Exception as e:
print(f"分析过程中出现错误: {e}")
if __name__ == "__main__":
main()
数据样例(house_sales_data.csv):复制表格数据就行
house_id | area(平方米) | bedrooms(卧室数) | bathrooms(卫生间数) | location(区域) | age(房龄) | price(价格/元) | sale_date(销售日期) | sale_status(销售状态) |
---|---|---|---|---|---|---|---|---|
1 | 120 | 3 | 2 | 朝阳区 | 5 | 6500000 | 2025-01-15 | 已售 |
2 | 85 | 2 | 1 | 海淀区 | 8 | 4800000 | 2025-01-16 | 已售 |
3 | 150 | 4 | 3 | 西城区 | 3 | 9500000 | 2025-01-17 | 待售 |
4 | 95 | 2 | 2 | 东城区 | 12 | 5200000 | 2025-01-18 | 签约中 |
5 | 180 | 4 | 3 | 丰台区 | 2 | 8200000 | 2025-01-19 | 已售 |
6 | 110 | 3 | 2 | 朝阳区 | 7 | 6800000 | 2025-01-20 | 已售 |
7 | 75 | 1 | 1 | 海淀区 | 15 | 3500000 | 2025-01-21 | 待售 |
8 | 130 | 3 | 2 | 西城区 | 6 | 7800000 | 2025-01-22 | 已售 |
9 | 100 | 2 | 2 | 东城区 | 10 | 5500000 | 2025-01-23 | 签约中 |
10 | 160 | 4 | 3 | 丰台区 | 4 | 9200000 | 2025-01-24 | 已售 |
11 | 140 | 3 | 2 | 朝阳区 | 5 | 7200000 | 2025-01-25 | 待售 |
12 | 90 | 2 | 1 | 海淀区 | 9 | 4500000 | 2025-01-26 | 已售 |
13 | 170 | 4 | 3 | 西城区 | 2 | 9800000 | 2025-01-27 | 已售 |
14 | 105 | 3 | 2 | 东城区 | 8 | 5800000 | 2025-01-28 | 签约中 |
15 | 125 | 3 | 2 | 丰台区 | 3 | 7500000 | 2025-01-29 | 已售 |
16 | 155 | 4 | 3 | 朝阳区 | 4 | 8500000 | 2025-01-30 | 待售 |
17 | 80 | 2 | 1 | 海淀区 | 11 | 4200000 | 2025-01-31 | 已售 |
18 | 135 | 3 | 2 | 西城区 | 7 | 7900000 | 2025-02-01 | 已售 |
19 | 115 | 3 | 2 | 东城区 | 9 | 6200000 | 2025-02-02 | 签约中 |
20 | 145 | 4 | 3 | 丰台区 | 5 | 8800000 | 2025-02-03 | 已售 |