python 二手车数据分析以及价格预测

二手车交易信息爬取、数据分析以及交易价格预测

  • 引言
  • 一、数据爬取
    • 1.1 解析数据
    • 1.2 编写代码爬
      • 1.2.1 获取详细信息
      • 1.2.2 数据处理
  • 二、数据分析
    • 2.1 统计分析
    • 2.2 可视化分析
  • 三、价格预测
    • 3.1 价格趋势分析(特征分析)
    • 3.2 价格预测

引言

本文着眼于车辆信息,结合当下较为火热的二手车交易市场数据,对最近二手车的交易价格进行分析以及预测。
经过前期调研,最终决定通过爬取一些网站的二手车数据和一些公开的数据集,分析交易数据的特征,根据交易特征对二手车交易价格进行分析预测。
本文主要核心内容:数据爬取数据分析交易价格预测

一、数据爬取

1.1 解析数据

  1. 选择二手车交易网站-瓜子二手车。点开官网,点击我要买车。以QQ浏览器为例,点击开发者工具(菜单-工具中),选择Network-DOC过滤。获取头部cookie等相关信息,如下图所示。
    在这里插入图片描述
  2. 通过搜索框(点击开发者工具页面右上角 ‘竖着的三个点’ - Search),输入页面商品名称和属性名称,获取想要数据的位置,方便后续爬取解析,如下图所示。
    在这里插入图片描述
  3. 根据以上获取的信息构造程序的headers以及编写具体数据的爬取代码

1.2 编写代码爬

1.2.1 获取详细信息

# 获取详细数据的 url
def get_detail_url(url, headers):rq = requests.get(url, headers=headers)soup = BeautifulSoup(rq.text, 'lxml')content = soup.find(class_='carlist clearfix js-top')links = content.find_all('a')detail_url_list = []for link in links:detail_url_list.append(f"https://www.guazi.com{link['href']}")return detail_url_list# 获取详情数据
def get_detail(url, headers):rq = requests.get(url, headers=headers)soup = BeautifulSoup(rq.text, 'lxml')# namecontent = soup.find(class_='product-textbox')title = content.find('h1').text# info (上牌时间为图片)  里程数 排量 变速箱info = content.find(class_='assort clearfix')span = info.find_all('span')if len(span) >= 4:info_dic = {'name': title.strip(), 'km': span[1].text, 'displacement': span[2].text, 'gearbox': span[3].text}else:  # 某些网页 span数据较少info_dic = {'name': title.strip(), 'km': span[1].text, 'displacement': '无', 'gearbox': '无'}# price 价格单位是万price = soup.find(class_='price-num')  # price-num  pricebox js-dispriceprice = price.text# 销售方seller = soup.find(class_='ten')seller = seller.find(class_='typebox')seller = seller.text# 燃油类型fuel = soup.find_all(class_='td2')  # 很多信息  第十五个是燃油类型 或者 没有信息horsepower = "无"if len(fuel)>=13:horsepower = fuel[12].textif len(fuel)>=15:fuel = fuel[14].textelse:fuel = "无"# fuelreturn info_dic, price, seller, fuel,horsepower

1.2.2 数据处理

  1. 数据集补充
    网站上的数据爬取难度较高,且数据量较少,一直爬取容易被封IP,所以这里使用公开赛的一个数据集对数据进行补充------阿里天池的二手车交易价格预测数据集,其数据具体内容如下图所示。
    在这里插入图片描述

  2. 统一数据格式
    网站上爬取的数据与公开赛数据集的数据是不一致的,相对来说公开赛数据集的标签比较多,信息比较详细,且数据类型单一,方便后续处理。所以这里需要对两个数据集进行统一,爬取的数据向公开赛数据靠拢,并将其转换为同一单位(比如fuelType网站上的数据是汉字,而公开赛数据集里的数据为数字,为了较少存储内存以及方便数据的后续处理,在这里将其统一为数字),同时删除无法在网站上爬取的公开赛数据中的标签

  3. 代码

name = []
fuelType = []
gearbox = []
power = []
kilometer = []
seller = []
price = []
# 爬取 保存数据
for page in range(1,3):print("************第{}页正在保存**********".format(page)) # 每一页 数量不定base_url = 'https://www.guazi.com/sjz/buy/o{}/#bread'.format(page) #detail_url = get_detail_url(base_url, headers)  # 所有车辆详细信息链接print(len(detail_url))for d_url in detail_url:print(d_url)info_dic, pric, sell, fuel, horsepower = get_detail(d_url, headers)name.append(info_dic['name'])  # 名字if fuel.find("汽油"):fuel = 0elif fuel.find("柴油"):fuel = 1elif fuel.find("液化石油气"):fuel = 2elif fuel.find("天然气"):fuel = 3elif fuel.find("混合动力"):fuel = 4else:fuel = 6fuelType.append(fuel)           # 燃油类型tmp = info_dic['gearbox']if tmp.find("手动"):tmp = 0else:                           # 电动汽车 大多是自动挡tmp = 1gearbox.append(tmp)             # 变速箱 自动 or 手动tmp = re.findall("\d+", horsepower)if len(tmp) == 0:tmp = 0else:tmp = int(tmp[0]) * 0.735power.append(tmp)                # 功率km = re.findall(r"\d+\.?\d*", info_dic['km'])if len(km) == 0:km = 0else:km = float(km[0])kilometer.append(km)             # 里程数if sell.find("私户"):sell = 0else:sell = 1seller.append(sell)              # 销售方、tmp = re.findall(r"\d+\.?\d*", pric)if len(tmp) == 0:tmp = 0else:tmp = float(tmp[0]) * 10000price.append(tmp)                # 价格df = pd.DataFrame({'name'    : name,'fuelType': fuelType,'gearbox' : gearbox ,'power'   : power,'kilometer': kilometer,'seller'  : seller,'price'   : price})
df.to_csv('guazi.csv')  # 最终保存为csv文件

二、数据分析

2.1 统计分析

  1. 公开数据集为例,这里只显示了其部分标签列(共30列),一共有15万条交易数据。可以看到每一个数据的SaleID都是不同的,从0递增到149999,name标签最大为19万,但是其一共只有15万条数据,想必name的分布也是相对均匀的。model是车型编码,最大为247,数据中车辆种类一共不超过248种。之后标签的max都很小,其分布相对密集。
    在这里插入图片描述
  2. 查看数据类型、缺失和异常值
    在这里插入图片描述
  3. 代码
#!/usr/bin/env python
# coding: utf-8
## 导入所需包
import numpy as np
import pandas as pd
import warnings
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.special import jn
from IPython.display import display, clear_output
import time
import pickle
warnings.filterwarnings('ignore')
## 在Jupyter noteboo显示图像
get_ipython().run_line_magic('matplotlib', 'inline')
from sklearn import linear_model  ## 模型预测的
from sklearn import preprocessing
from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor,GradientBoostingRegressor
from sklearn.decomposition import PCA,FastICA,FactorAnalysis,SparsePCA ## 数据降维处理的
import lightgbm as lgb
import xgboost as xgb
## 参数搜索和评价的
from sklearn.model_selection import GridSearchCV,cross_val_score,StratifiedKFold,train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error#Train_data = pd.read_csv('used_car_train_20200313.csv', sep=' ') # shape: (150000, 40)
Train_data = pd.read_csv('guazi.csv', sep=',') # shape: (150000, 40)# In[10]:
pd.set_option('display.max_rows', 500)
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
print(Train_data.describe())# In[11]:
Train_data.head()# In[12]:
Train_data.info()# In[13]:
Train_data.isnull().sum()

2.2 可视化分析

在这里插入图片描述

#!/usr/bin/env python
# coding: utf-8
## 导入所需包
import numpy as np
import pandas as pd
import warnings
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.special import jn
from IPython.display import display, clear_output
import time
import pickle
warnings.filterwarnings('ignore')
## 在Jupyter noteboo显示图像
get_ipython().run_line_magic('matplotlib', 'inline')
from sklearn import linear_model  ## 模型预测的
from sklearn import preprocessing
from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor,GradientBoostingRegressor
from sklearn.decomposition import PCA,FastICA,FactorAnalysis,SparsePCA ## 数据降维处理的
import lightgbm as lgb
import xgboost as xgb
## 参数搜索和评价的
from sklearn.model_selection import GridSearchCV,cross_val_score,StratifiedKFold,train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error#Train_data = pd.read_csv('used_car_train_20200313.csv', sep=' ') # shape: (150000, 40)
Train_data = pd.read_csv('guazi.csv', sep=',') 
# In[3]:
plt.hist(Train_data['price'])
plt.show()
# In[4]:
features = Train_data.columns
#print(features)
features = [col for col in features if col not in ['price','notRepairedDamage']]
f = pd.melt(Train_data, value_vars=features)
g = sns.FacetGrid(f, col="variable",  col_wrap=2, sharex=False, sharey=False)
g = g.map(sns.distplot, "value")
# In[ ]:

三、价格预测

爬取的车辆数据集特征数量较少,能否准确预测交易价格?

3.1 价格趋势分析(特征分析)

  1. 按照爬取数据集的特征选取公开赛数据集的部分特征,然后将其分为训练集和验证集,训练集用于训练,验证集用于验证训练的模型的好坏(模型采用xgboost),然后对爬取数据进行测试,查看预测价格与实际价格的分布是否大致相同。
    以下是结果图,黄色表示为实际价格,蓝色为预测价格*6,由于公开赛数据集的二手车交易价格普遍较低,所以预测出来的价格也相对实际价格较低,这里乘以6是为了方便观察其价格分布。
    在这里插入图片描述
  2. 可以看到实际价格和预测价格的趋势大致相同,再计算以下他们的相关性,如下图。
    在这里插入图片描述
  3. 代码
## 导入所需包
import pandas as pd
import matplotlib.pyplot as plt
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
Train_data = pd.read_csv('used_car_train_20200313.csv', sep=' ') # shape: (150000, 40)
## 查看列
#print(Train_data.columns)
cols = Train_data.columns
## 选择特征列
feature_cols =['fuelType','gearbox','power','kilometer','seller']
## 构造训练样本和测试样本
X_data = Train_data[feature_cols]
Y_data = Train_data['price']
def build_model_lgb(x_train,y_train):model = lgb.LGBMRegressor(objective='regression',max_depth = 10,num_leaves = 1000,learning_rate=0.1, n_estimators=100,metric='rmse',  #bagging_fraction = 0.8, feature_fraction = 0.8)model.fit(x_train, y_train)return model
x_train,x_val,y_train,y_val = train_test_split(X_data,Y_data,test_size=0.2)
# 训练模型
print('Predict lgb...')
model_lgb = build_model_lgb(x_train,y_train)
print('ok!')
# 测试模型
val_lgb = model_lgb.predict(x_val)
val_lgb[val_lgb<0] = 0
MAE_lgb = mean_absolute_error(y_val,val_lgb)
print('MAE of val with lgb:',MAE_lgb)
MAE = mean_absolute_error(y_val,val_lgb*0.5)
print('MAE:',MAE)Test = pd.read_csv('guazi.csv', sep=',') # shape
test_price = model_lgb.predict(Test[feature_cols])
#mean_absolute_error(Test['price'],test_price)
plt.plot(test_price*6)
plt.plot(Test['price'])
plt.show()
data = pd.DataFrame({'predict':test_price,'gt':Test['price']})
t2=data.corr()
print(t2)

3.2 价格预测

  1. 通过对价格趋势的分析,有理由相信爬取的有限的这几个特征:['fuelType','gearbox','power','kilometer','seller'],在一定程度上影响着车辆的价值。同时由于公开赛数据集的价格与爬取数据集的价格相差很大,所以没有办法使用公开赛数据集对爬取数据集做定量分析。只能爬取跟多的二手车数据集对二手车交易价格做定量的预测。

  2. 相对于价格趋势分析,这里同样使用的是lgb模型,但是为了价格预测的准确性,将学习率降低为0.01,迭代次数增加为十万次。其测试误差如下(MAE-平均绝对误差7755):
    在这里插入图片描述

  3. 查看实际价格与预测价格的折线图:
    在这里插入图片描述

  4. 代码

#!/usr/bin/env python
# coding: utf-8
## 导入所需包
import numpy as np
import pandas as pd
import warnings
import matplotlib
import matplotlib.pyplot as plt
import time
import pickle
warnings.filterwarnings('ignore')
## 在Jupyter noteboo显示图像
get_ipython().run_line_magic('matplotlib', 'inline')
from sklearn import preprocessing
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_errorTrain_data = pd.read_csv('guazi_more.csv', sep=',') # shape: (150000, 40)
#TestA_data = pd.read_csv('used_car_testB_20200421.csv', sep=' ') # shape: (50000, 39)
Train_data.describe()# In[35]:
## 查看列
#print(Train_data.columns) 
cols = Train_data.columns
## 选择特征列
feature_cols =['fuelType','gearbox','power','kilometer','seller']
## 构造训练样本和测试样本
X_data = Train_data[feature_cols]
Y_data = Train_data['price']
x_train,x_val,y_train,y_val = train_test_split(X_data,Y_data,test_size=0.2)# In[62]:
def build_model_lgb(x_train,y_train):model = lgb.LGBMRegressor(objective='regression',max_depth = 10,num_leaves = 1000,learning_rate=0.01, n_estimators=100000, # 60000 7千   # metric='rmse',  #bagging_fraction = 0.8, feature_fraction = 0.8)model.fit(x_train, y_train)return model# In[63]:
# 训练模型
print('Predict lgb...')
model_lgb = build_model_lgb(x_train,y_train)
print('ok!')# In[64]:
# 测试模型
val_lgb = model_lgb.predict(x_val)
#val_lgb[val_lgb<0] = 0
MAE_lgb = mean_absolute_error(y_val,val_lgb)
print('MAE of val with lgb:',MAE_lgb) # In[68]:
x = np.arange(0,len(y_val),1)
plt.plot(x,val_lgb) # scatter
plt.plot(x,y_val)
plt.figure(figsize=(30,10),dpi=36)
plt.show()# In[69]:
data = pd.DataFrame({'predict':val_lgb,'gt':y_val})
t2=data.corr()
print(t2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/111515.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java面试题记录

一、多线程、高并发&#xff1a; 1.1 什么是死锁&#xff0c;怎样解决死锁问题&#xff1f; 死锁指的是由于两个或两个以上的线程互相持有对方所需要的资源&#xff0c;同时等待获取对方释放自己所需要的资源&#xff0c;导致这些线程处于等待中而无法往下进行的状态。 精简描述…

第一篇------Virtual I/O Device (VIRTIO) Version 1.1

1 介绍 本文档描述了“virtio”设备系列的规格。这些设备通常出现在虚拟环境中&#xff0c;但按设计&#xff0c;它们在虚拟机内部看起来像物理设备&#xff0c;而本文档将其视为这样的设备。这种相似性允许虚拟机内的客户端使用标准驱动程序和发现机制。 virtio及其规格的目的…

远程计算机控制软件

远程控制软件允许您连接和控制位于不同位置的设备&#xff0c;对于 IT 帮助台技术人员来说&#xff0c;这是一个很好的工具&#xff0c;可以通过与用户协作、与他们聊天以及安全地访问他们的文件来轻松排除故障和修复远程设备。使用远程控制软件&#xff0c;距离不再是提供技术…

Kotlin变量与控制条件的基本用法

一、变量与控制条件 1、var与val var&#xff1a;可修改变量 val&#xff1a;只读变量&#xff0c;只读变量并非绝对只读。 编译时常量只能在函数之外定义&#xff0c;因为函数内常量是在运行时赋值&#xff0c;编译时常量要在变量赋值前存在。并且值是无法修改的。 const…

VIRTIO-SCSI代码分析(2)VIRTIO 驱动分析

QEMU模拟出VIRTIO SCSI设备后&#xff0c;在虚拟机中呈现SCSI设备和PCIE设备。而在虚拟机中&#xff0c;PCIE设备与VIRTIO PCI驱动匹配触发virtio_pci_probe()注册生成virtio设备&#xff0c;而virtio设备与虚拟机中的virtio驱动匹配触发对应probe函数最终注册对应的驱动。 这里…

短视频搭建矩阵源码--短视频矩阵源码搭建

短视频矩阵系统是一种通过将短视频内容进行分类、管理和展示的系统。它可以将用户上传或者选择的短视频按照不同的特定标签进行分类和管理&#xff0c;用户可以根据自己的兴趣和需求选择观看不同类别的短视频。 短视频矩阵源码的开发部署其实并不难&#xff0c;主要依托于抖音平…

uniapp微信小程序《隐私保护协议》弹窗处理流程

背景 《关于小程序隐私保护指引设置的公告》 《小程序隐私协议开发指南》 流程 1.第一步 必须设置且审核通过&#xff01;&#xff01;&#xff01; 2.第二步 uniapp在manifest.json中添加&#xff01;&#xff01;&#xff01; /* 在 2023年9月15号之前&#xff0c;在 ap…

Apinto 网关: Go语言实现 HTTP 转 gRPC

gRPC 是由 Google 开发的一个高性能、通用的开源RPC框架&#xff0c;主要面向移动应用开发且基于 HTTP/2 协议标准而设计&#xff0c;同时支持大多数流行的编程语言。 gRPC 基于 HTTP/2 协议传输&#xff0c; HTTP/2 相比 HTTP1.x有以下优势: 采用二进制格式传输协议&#xff…

Flink JobManager的高可用配置

背景 在flink执行中&#xff0c;jobManager是一个负责执行流式应用执行和检查点生成的组件&#xff0c;一旦发生故障&#xff0c;那么其负责的所有应用都会被取消&#xff0c;所以我们需要对JobManager配置高可用的模式 JobManager高可用配置 配置JobManager的高可用需要使用…

Ae 效果:CC Hair

模拟/CC Hair Simulation/CC Hair CC Hair&#xff08;CC 毛发&#xff09;可以在源图像上模拟生成毛发、绒线等&#xff0c;并可调整它们的长度、方向、重量等属性&#xff0c;从而创建出非常独特的效果。 CC Hair 本质上是基于 Alpha 通道来生成毛发&#xff0c;无毛发处将变…

Python 文件写入操作

视频版教程 Python3零基础7天入门实战视频教程 w模式是写入&#xff0c;通过write方法写入内容。 # 打开文件 模式w写入&#xff0c;文件不存在&#xff0c;则自动创建 f open("D:/测试3.txt", "w", encoding"UTF-8")# write写入操作 内容写入…

Typora偏好设置中图床的配置文件点击打开没有反应

Typora偏好设置中图床的配置文件点击打开没有反应 突然发现Typora偏好设置中图床打开配置文件点击没有反应&#xff0c;如下按钮所示 可能是因为系统不知道用什么软件打开json&#xff0c;直接进入配置文件json目录&#xff0c;一般位置在C:\Users\<your_user_name>\.pi…