当前所在位置: 首页 > 维修大全

griddata三维空间插值「建议收藏」

2025-09-02 本站作者 【 字体:

大家好,又见面了,我是你们的朋友全栈君。

从这一篇文章,你将要学到

背景

最近在做一个项目,要为上海市13000+个普通住宅楼盘算基本价格,俗称基价,可以从第三方来的案例数据只能覆盖大约3000个楼盘,余下的10000楼盘难为无米之炊,联想到地形图的思想,把上海市所有楼盘的基价看成海拔,楼盘的经纬度就是位置所在,然后会在三维空间形成一个连续平滑的三维曲面,这里利用scipy的interpolate类里面的griddata函数小试牛刀。

数据

插值算法_scipy griddata_scipy griddata 安装

从原数据我们看到需要插值的thismonthprice有大量空缺,如何利用地理位置进行插值呢?基本思路如下

完整代码代码解读

主要由scatterPlot和gridInterpolate两个函数实现, 其中scatterPlot主要负责绘制散点图,图片如下

scipy griddata_插值算法_scipy griddata 安装

gridInterpolate主要负责插值功能

griddata基本调用格式如下

scipy.interpolate.griddata(points,values,xi,method ='linear',fill_value = nan,rescale = False )

浮点数的二维数组或一维数组的元组,形状(M,D)插值数据的点。

可选插值方法。{‘linear’,‘nearest’,‘cubic’},之一,其中 linear 将输入点设置为n维单纯形,并在每个单形上线性插值,可以简单理解为以三角形为基础,就是按Delaunay方法先找出内插点四周的3个点,构成三角形,内插点在三角形内.然后线性内插,或三次方程内插.。 nearest 返回最接近插值点的数据点的值。 cubic 返回由三次样条确定的值。 返回由分段立方,连续可微(C1)和近似曲率最小化多项式表面确定的值。

逐步插值

插值是一个逐步扩散的过程,如果让第一次插值的结果再参与训练的话,第二次插值效果会好一些,以此类推,循环下去,就可以逐步插值,最后会达到一种收敛状态,所以需要用一个标志其达到收敛了,最简单的判断方式就是插值数据不再提升了就认为收敛了。

# -*- coding: utf-8 -*-
""" Project_name:逐步插值 Description:多次插值实现无案例楼盘基价赋值 Created on Tue Oct 20 17:59:08 2020 @author: 帅帅de三叔 """
import numpy as np #导入数值计算模块
import pandas as pd #导入数据分析模块
from scipy import stats
import matplotlib.pyplot as plt #导入绘图模块
from mpl_toolkits.mplot3d import Axes3D #导入3d绘图模块
from matplotlib import cm #颜色调整用
from scipy.interpolate import griddata #导入插值类
def scatterPlot(data): #绘制绘图函数
    plt.figure(figsize = (9, 7)) #新建画布
    caseData = data.dropna(subset = ["thismonthprice"]) #去掉空值,保留本月有价格的数据留作插值依据
    lon = caseData["lon"] #经度
    lat = caseData["lat"] #纬度
    
    interpolateData = data[data["thismonthprice"].isnull()] #待插值的数据
    x = interpolateData["lon"] #待插值的楼盘经度
    y = interpolateData["lat"] #待插值的楼盘纬度
    plt.scatter(lon, lat, s = 5, color = "r", label = "no need interpolate") #不需要插值的散点图
    plt.scatter(x, y, s = 5, color = "b", alpha = 0.2,  label = "need interpolate") #需要插值的散点图
    plt.legend()
    plt.show()
def gridInterpolate(data): #定义插值函数,data需要有newdiskid, lon,lat, 上个月价格,本月价格(有空缺)
    casenum = [] #用来存放有价格的楼盘数
    interpolatenum = [] #用来存放待插值的样本数
    caseData = data.dropna(subset = ["thismonthprice"]) #去掉空值,保留本月有价格的数据留作插值依据
    casenum.append(len(caseData)) #追加有价格的样本数
    casediskid = caseData["newdiskid"] #楼盘id
    lon = caseData["lon"] #经度
    lat = caseData["lat"] #纬度
    z = caseData["thismonthprice"] #价格
    
    interpolateData = data[data["thismonthprice"].isnull()] #待插值的数据
    interpolatenum.append(len(interpolateData)) #追加待插值样本数
    interpolatediskid = interpolateData["newdiskid"] #待插值的楼盘id
    x = interpolateData["lon"] #待插值的楼盘经度
    y = interpolateData["lat"] #待插值的楼盘纬度
    xx, yy = np.meshgrid(x, y) #平面网格点待插值的位置
    zz = griddata((lon, lat), z, (xx, yy), method='nearest', fill_value = z.median(), rescale = True) #stats.mode(z)[0][0]在没有价格的网格点插值
    Z = pd.DataFrame(zz) #数据框化
    interpolateprice = [] #用来存放插值
    for i in range(Z.shape[0]):
        interpolateprice.append(Z[i][i]) #取对角线上的元素
        
    label1 = pd.Series(np.zeros(len(casediskid))) #有价格的标签
    casedf = pd.concat([casediskid, z], axis = 1).reset_index()[["newdiskid", "thismonthprice"]] #索引重置
    casedf = pd.concat([casedf, label1], axis = 1)
    casedf.columns = ["newdiskid", "z", "label"]
    
    label2 = pd.Series(np.ones(len(interpolatediskid))) #插值标签
    interpolatedf = pd.DataFrame({ 
   "interpolatediskid":interpolatediskid, "interpolateprice": interpolateprice}).reset_index()[["interpolatediskid", "interpolateprice"]]
    interpolatedf = pd.concat([interpolatedf, label2], axis = 1)
    interpolatedf.columns = ["newdiskid", "z", "label"]    
    result = pd.concat([casedf, interpolatedf], ignore_index = True) #纵向拼接
    interpolateresult = pd.merge(data, result, how = "left") #匹配
    interpolateresult["diff"] = np.abs(interpolateresult["z"] - interpolateresult["lastmonthprice"])/interpolateresult["lastmonthprice"]  #绝对偏差率
    for i in range(len(interpolateresult)): #利用插值更新本月基价
        if interpolateresult["label"][i] == 1 and interpolateresult["diff"][i]< 0.05: #如果插值的绝对误差率小于0.05填补空缺价格
            interpolateresult["thismonthprice"][i] = interpolateresult["z"][i]
    interpolateresult.to_excel("无案例楼盘interpolateresult.xlsx")
    return casenum, interpolatenum, interpolateresult[["newdiskid","plate", "newdiskname", "villa", "lon", "lat", "lastmonthprice", "thismonthprice"]] #返回更新本月基价的数据框
if __name__ == "__main__":
    data = pd.read_excel("无案例楼盘逐步插值.xlsx") #读取数据
    scatterPlot(data)
    casenum, interpolatenum, data = gridInterpolate(data)
    print(casenum[-1], len(data.dropna(subset = ["thismonthprice"])))
    for i in range(10):
        if casenum[-1] < len(data.dropna(subset = ["thismonthprice"])): #未收敛则继续插值
            casenum, interpolatenum, data = gridInterpolate(data)
            scatterPlot(data)
            print(casenum[-1], len(data.dropna(subset = ["thismonthprice"])))

插值动态图如下,从动图可以看到需要插值的越来越少,即图中的蓝色的越来越少,反观红色的越来越多。

scipy griddata 安装_插值算法_scipy griddata

总结

插值还是很消耗资源的,所以比较慢,用3000个插值10000个,有种四两拨千斤的感觉,最后效果不会特别好,比如插值到收敛了一共插值出6000个,相当于填补了一部分数据标签,这为以后的机器学习模型提供了基础。

阅读全文
加载中~
相关推荐

SKG破壁机,爱上下厨的理由?

SKG破壁机,爱上下厨的理由?
作为一个几乎不下厨房的人,其实有着一颗想当厨娘的心,并一直坚信自己很有厨师天分,...

住宅专项维修资金按什么标准来收取

住宅专项维修资金按什么标准来收取
摘要:住宅专项维修资金,是用来维修相关的设施的费用,那么住宅专项维修资金按什么标...

体验分享乐趣 佳能MG7580一体机试用评测

体验分享乐趣 佳能MG7580一体机试用评测
外观展示笔者试用评测的这台佳能腾彩PIXMA MG7580喷墨多功能照片一体机为...

火花塞可以自己换吗?老司机告诉你方法和其中的风险

火花塞可以自己换吗?老司机告诉你方法和其中的风险
火花塞是车上的一个点火装置,像一个打火机,在发动机运转时负责点燃汽油混合气的。它...

北京森歌集成灶维修电话售后服务400热线全市统一报修网点《今日发布》

北京森歌集成灶维修电话售后服务400热线全市统一报修网点《今日发布》
北京森歌集成灶维修电话售后服务400热线全市统一报修网点《今日发布》:400-9...

为什么现在修车行业没人干了?修车改行的都干嘛去了?

为什么现在修车行业没人干了?修车改行的都干嘛去了?
新的一年,可能大家会有所发现,好像又有部分以前干汽车修理的离职不干了,所以很多人...

月薪过万难招一名汽修工 新能源车4S店四处网罗“三电”熟手师傅

月薪过万难招一名汽修工 新能源车4S店四处网罗“三电”熟手师傅
深圳新闻网2025年7月30日讯(深圳晚报记者 林咪玲 实习生 吴雪玉)绿牌车满...

5000亿住宅维修基金沉睡 小区公共收益成糊涂账

5000亿住宅维修基金沉睡 小区公共收益成糊涂账
5000亿住宅维修基金现状:使用难、监管难、增值难  新华社最近一篇关于住房专项...

沧州学挖掘机哪里好?培训办证多少钱?

沧州学挖掘机哪里好?培训办证多少钱?
沧州学挖掘机哪里好?培训办证多少钱?沧州没有大型的挖掘机培训学校,学挖掘机可以到...

房屋维修基金你用过吗 青岛这五种情况不能动

房屋维修基金你用过吗 青岛这五种情况不能动
青岛新闻网4月14日讯 房屋的保修期限是多长?哪种情况可以申请使用房屋维修基金?...
本站访客:68699
1097476955
服务热线

服务热线

18951535724

18951535724
返回顶部