大数据分析之缺失值处理,多种方法带你轻松搞定
在Python中处理缺失值至关重要,因为缺失值可能导致数据分析结果出现偏差,影响模型的准确性和可靠性。如果不对缺失值进行处理,统计分析可能会产生误导性的结论,机器学习模型也可能因为数据的不完整性而无法有效学习数据中的模式。

因此,选择合适的数据处理方法对于维持数据完整性并提升模型训练效率至关重要。
常见的数据缺失值处理方法包括:
1、删除含有缺失值的行或列:简单直接,但可能丢失重要信息。
2、填充缺失值:使用均值、中位数、众数等统计量填充。
3、插值法:利用已知数据点估计缺失值。
4、模型预测:使用模型预测缺失值。
5、多重插补:生成多个数据集,每个数据集都有不同的缺失值填充。
6、热卡填充:使用相似数据点的值填充。
7、最近邻法:找到最近的非缺失值点进行填充。
8、回归分析:利用其他变量预测缺失值。
9、聚类分析:将数据分为若干个簇,每个簇内部填充缺失值。
10、基于知识的填充:利用领域知识或业务规则填充。
从数据缺失值填充实现工具的角度,有基于pandas的,有基于numpy的,有基于sklearn的,有基于XGBoost的,有基于随机森林的。
本文无法全部实现,涵盖了一些常用工具和常用处理方法。
本文数据来自于Meteostat,它 是一个开源的 Python 库,旨在提供简单高效的接口来访问全球范围内的历史和实时气象数据。它支持全球成千上万的气象站,能够提供月度、每日和每小时的数据记录,当然在数据采集的过程中,也存在数据缺失的情况,甚至长达数月。我们就以此为例来进行数据缺失值算法探讨。
第一段代码,主要是基础库导入、定义了一个pandas缺失值比例函数、对pandas数据进行格式化展示
from meteostat import Daily, Hourly, Monthly, Stations
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer,KNNImputer
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
# ---------------------------------------查看pandas缺失情况-----------------------------------------
def pandasnullinfo(df):
missing = df.isna().sum()
missing = pd.DataFrame(data={'feature_name': missing.index, 'null_value_num': missing.values})
# 通过~取反,选取不包含数字0的行
missing = missing[~missing['null_value_num'].isin([0])]
# 缺失比例
missing['null_value_ratio'] = missing['null_value_num'] / df.shape[0]
return missing
# ---------------------------------------对pandas显示进行格式化-----------------------------------------
# 显示所有列
pd.set_option('display.max_columns', None)
# 显示所有行
pd.set_option('display.max_rows', None)
# 不换行显示
pd.set_option('display.width', 1000)
# 行列对齐显示,显示不混乱
pd.set_option('display.unicode.ambiguous_as_wide', True)
pd.set_option('display.unicode.east_asian_width', True)
# 显示精度
pd.set_option('display.precision', 4)
# 显示小数位数
pd.get_option("display.precision")
第二段代码,主要是获取某个气象站的数据,构造了等同的新列,按照一定的概率随机赋值为空,后续将新列数据和原始数据做对比。
# ---------------------------------------对获取气象的参数进行构造-----------------------------------------
startdate=datetime(2024,12,1)
enddate=datetime(2024,12,31)
citycode=59758
# ---------------------------------------通过meteostat获取气象信息-----------------------------------------
dailydata=Daily(citycode,startdate,enddate)
dailyinfo=dailydata.fetch()
# ---------------------------------------在pandas构造缺失值-----------------------------------------
dailyinfo['tavgtemp']=dailyinfo['tavg']
dailyinfo['tmintemp']=dailyinfo['tmin']
dailyinfo['tmaxtemp']=dailyinfo['tmax']
dailyinfo['prcptemp']=dailyinfo['prcp']
dailyinfo['wdirtemp']=dailyinfo['wdir']
dailyinfo['wspdtemp']=dailyinfo['wspd']
dailyinfo['prestemp']=dailyinfo['pres']
# 为'tavgtemp'等列随机赋空值,赋值的概率为20%
dailyinfo['tavgtemp'] = np.where(np.random.choice([True, False], size=len(dailyinfo), p=[0.8, 0.2]), dailyinfo['tavgtemp'], np.nan)
dailyinfo['tmintemp'] = np.where(np.random.choice([True, False], size=len(dailyinfo), p=[0.8, 0.2]), dailyinfo['tmintemp'], np.nan)
dailyinfo['tmaxtemp'] = np.where(np.random.choice([True, False], size=len(dailyinfo), p=[0.8, 0.2]), dailyinfo['tmaxtemp'], np.nan)
dailyinfo['prcptemp'] = np.where(np.random.choice([True, False], size=len(dailyinfo), p=[0.9, 0.1]), dailyinfo['prcptemp'], np.nan)
dailyinfo['wdirtemp'] = np.where(np.random.choice([True, False], size=len(dailyinfo), p=[0.9, 0.1]), dailyinfo['wdirtemp'], np.nan)
dailyinfo['wspdtemp'] = np.where(np.random.choice([True, False], size=len(dailyinfo), p=[0.85, 0.15]), dailyinfo['wspdtemp'], np.nan)
dailyinfo['prestemp'] = np.where(np.random.choice([True, False], size=len(dailyinfo), p=[0.85, 0.15]), dailyinfo['prestemp'], np.nan)
dailyinfo.drop(columns=['snow'], inplace=True)
dailyinfo.drop(columns=['wpgt'], inplace=True)
dailyinfo.drop(columns=['tsun'], inplace=True)
# tavg 平均气温,单位为°C Float64
# tmin 最低空气温度,单位为°C Float64
# tmax 最高空气温度,单位为°C Float64
# prcp 日降水总量,单位为mm Float64
# snow 日降雪量,以毫米为单位的雪深度 Float64
# wdir 以度(°)为单位的平均风向 Float64
# wspd 以km/h为单位的平均风速 Float64
# wsgt 以km/h为单位的每日最大风速 Float64
# pres 海平面平均气压,单位为hPa Float64
# tsun 每日日照时长,单位为h小时 Float64
# print(dailyinfo.describe())
# tavg tmin tmax prcp snow wdir wspd wpgt pres tsun tavgtemp tmintemp tmaxtemp prcptemp wdirtemp wspdtemp prestemp
# count 31.000031.000031.000031.0000 0.031.000031.0000 0.0 31.0000 0.0 25.0000 21.0000 21.0000 26.0000 28.0000 29.0000 25.0000
# mean 19.551617.251622.3613 0.3194 NaN 61.451612.0226 NaN 1018.8613 NaN 19.3200 17.1810 22.5333 0.3808 61.9286 12.15521018.9320
# std 2.2717 2.4942 2.6361 1.0756 NaN 14.7983 2.1271 NaN 3.1995 NaN 2.3267 2.3377 2.6377 1.1679 15.5133 2.1340 3.3913
# min 15.800013.000017.9000 0.0000 NaN 26.0000 8.1000 NaN 1013.7000 NaN 15.8000 14.0000 17.9000 0.0000 26.0000 8.10001013.7000
# 25% 17.950014.700020.2000 0.0000 NaN 54.500010.6000 NaN 1015.6000 NaN 17.8000 14.8000 20.4000 0.0000 51.7500 10.70001015.0000
# 50% 19.000017.100021.8000 0.0000 NaN 65.000011.8000 NaN 1019.6000 NaN 18.3000 17.1000 22.4000 0.0000 66.0000 12.10001019.6000
# 75% 21.200019.550025.0500 0.0000 NaN 72.500013.7000 NaN 1020.5000 NaN 21.1000 18.6000 25.3000 0.0000 73.2500 14.00001020.9000
# max 23.800021.500026.6000 5.8000 NaN 87.000015.4000 NaN 1024.6000 NaN 23.8000 21.5000 26.6000 5.8000 87.0000 15.40001024.6000
# 统计每列NaN的数量
nancounts = pandasnullinfo(dailyinfo)
# print(nancounts)
# feature_name null_value_num null_value_ratio
# 7 tavgtemp 9 0.2903
# 8 tmintemp 5 0.1613
# 9 tmaxtemp 5 0.1613
# 10 prcptemp 3 0.0968
# 11 wdirtemp 2 0.0645
# 12 wspdtemp 4 0.1290
# 13 prestemp 5 0.1613
第三段代码是基于pandas的fillna、ffill,bfill进行缺失值填充,fillna主要包括常量填充、平均值填充、中位数填充、众数填充,按照条件填充缺失值,这些相对比较简单,但误差率也高。
# ---------------------------------------通过pandas自带的函数处理缺失值-----------------------------------------
# 使用缺省值填充
dailyinfo_fillna = dailyinfo.fillna(0)
# 使用前一个值填充缺失值,当第一行是空值时,无法填充
dailyinfo_ffill = dailyinfo.ffill()
# 使用后一个值填充缺失值,当最后一行是空值时,无法填充
dailyinfo_bfill = dailyinfo.bfill()
# 使用列平均值填充缺失值
dailyinfo_mean = dailyinfo.fillna(dailyinfo.mean())
# 使用列的中位数填充缺失值
dailyinfo_median = dailyinfo.fillna(dailyinfo.median())
# 使用列的众数填充缺失值
dailyinfo_mode = dailyinfo.fillna(dailyinfo.mode().iloc[0])
# 根据条件填充缺失值
# dailyinfo['tavgtemp'] = dailyinfo['tavgtemp'].fillna(dailyinfo['tavg'])
第四段代码是基于pandas的interpolate即插值函数来填充,这里也提供了多种插值参数,需要注意的是插值函数无法保证所有缺失值都能填充,尤其是首行、尾行,因此需要对仍缺失的值按最简单的bfill,ffill进行填充。
# ---------------------------------------通过pandas自带的插值函数处理缺失值-----------------------------------------
# pandas.interpolate(method='linear', axis=0, limit=None, inplace=False, limit_direction='forward', limit_area=None, downcast=None, **kwargs)
# 参数说明:
# method:指定插值方法,默认为线性插值,可选的方法有'linear'、'time'、'index'、'values'、'nearest'、'zero'、'slinear'、'quadratic'、'cubic'、'polynomial',具体使用哪种方法取决于数据的特点和需求。
# 线性插值法:method='linear',是最常用的插值方法,通过已知数据点之间的线性关系来估计未知的数据
# 基于时间的插值:method=‘time’,如果数据集中存在时间序列数据,可以尝试使用基于时间的插值方法。
# 二次插值:method=‘quadratic’,二次插值通过已知的数据点构建一个二次多项式来逼近未知的数值。
# 三次插值:method=‘cubic’,三次插值是一种常用的插值方法,通过已知的数据点构建一个三次多项式来逼近未知的数值。
# 三次样条插值:三次样条插值相比于简单的三次插值更加灵活和准确,因为它提供了更高的插值精度和更好的曲线平滑性。
# 拉格朗日插值:拉格朗日插值使用拉格朗日多项式逼近已知数据点,通过构造一个通过所有数据点的插值多项式来估计其他点的数值。
# ‘index’, ‘values’: 使用索引的实际数值
# ‘pad’:使用现有值填写NaN。
# axis:指定插值的轴,默认为0,表示按列进行插值操作。
# limit:指定连续缺失值的最大数量,超过该数量的缺失值将不会被插值,默认为None,表示不限制数量。
# inplace:指定是否在原始数据上进行插值操作,默认为False,表示生成新的插值后的数据副本。
# limit_direction:指定插值的方向,默认为'forward',表示向前插值,可选的值还有'backward'和'both'。
# limit_area:指定插值的区域,默认为None,表示不限制区域,可选的值有'inside'和'outside'。
# downcast:指定插值后数据的类型,默认为None,表示不进行类型转换。
# 。例如,如果你的数据是时间序列,并且你知道数据的自然增长趋势,那么使用time或index方法可能更合适;
# 如果你需要平滑的曲线拟合,可以考虑使用spline或polynomial方法。
# 对于简单的替换策略,如最近邻或零插值,可以直接使用nearest或zero方法。
# linear 线性插值,缺省linear,通过计算相邻点之间的线性回归来估计缺失值,其他首行和尾行需要借助ffbill和bfill来填充
dailyinfo_linear=dailyinfo.interpolate(method='linear')
dailyinfo_linear.ffill(inplace=True)
dailyinfo_linear.bfill(inplace=True)
# interpolate 基于时间的插值,这种方法假定数据的时间序列性质,并基于时间顺序进行插值。通常用于时间序列数据。
dailyinfo_time=dailyinfo.interpolate(method='time')
dailyinfo_time.ffill(inplace=True)
dailyinfo_time.bfill(inplace=True)
# values:基于周围的非缺失值进行插值。这是一种简单的替换方法,将缺失值替换为最近的非缺失值。
dailyinfo_values=dailyinfo.interpolate(method='values')
dailyinfo_values.ffill(inplace=True)
dailyinfo_values.bfill(inplace=True)
# nearest:最近邻插值。它将每个缺失值替换为最近的非缺失观测值
dailyinfo_nearest=dailyinfo.interpolate(method='nearest')
dailyinfo_nearest.ffill(inplace=True)
dailyinfo_nearest.bfill(inplace=True)
# slinear 线性插值,三次样条的线性插值
dailyinfo_slinear=dailyinfo.interpolate(method='slinear')
dailyinfo_slinear.ffill(inplace=True)
dailyinfo_slinear.bfill(inplace=True)
# quadratic 二次插值,三次样条的二次插值
dailyinfo_quadratic=dailyinfo.interpolate(method='quadratic')
dailyinfo_quadratic.ffill(inplace=True)
dailyinfo_quadratic.bfill(inplace=True)
# cubic 三次插值,三次样条的三次插值
dailyinfo_cubice=dailyinfo.interpolate(method='cubic')
dailyinfo_cubice.ffill(inplace=True)
dailyinfo_cubice.bfill(inplace=True)
# polynomial:多项式插值,可以通过指定order参数来指定多项式的阶数,例如order=2为二次多项式
dailyinfo_polynomial=dailyinfo.interpolate(method='polynomial', order=2)
dailyinfo_polynomial.ffill(inplace=True)
dailyinfo_polynomial.bfill(inplace=True)
# method='barycentric',适用于快速增长的时间序列
dailyinfo_barycentric=dailyinfo.interpolate(method='barycentric', order=2)
dailyinfo_barycentric.ffill(inplace=True)
dailyinfo_barycentric.bfill(inplace=True)
# method='pchip',适用于值接近累积分布函数
dailyinfo_pchip=dailyinfo.interpolate(method='pchip', order=2)
dailyinfo_pchip.ffill(inplace=True)
dailyinfo_pchip.bfill(inplace=True)
# spline:样条插值,可以通过order参数来控制样条的阶数。默认情况下,order=1对应于线性样条,order=2对应于二次样条,以此类推
dailyinfo_spline=dailyinfo.interpolate(method="spline", order=2)
dailyinfo_spline.ffill(inplace=True)
dailyinfo_spline.bfill(inplace=True)
第五段代码是基于sklearn的SimpleImputer和KNNImputer来进行填充,SimpleImputer其实和第三段中pandas的简单填充很类似。
# ---------------------------------------通过sklearn中带的SimpleImputer进行缺失值填充-----------------------------------------
dailyinfocopy= dailyinfo.copy()
dailyinfocopy_mean = SimpleImputer(missing_values=np.nan, strategy='mean').fit_transform(dailyinfocopy)
# 方法一,但时间序列就没有了
dailyinfocopy_mean_copy1 = pd.DataFrame(dailyinfocopy_mean, columns=dailyinfocopy.columns)
# print(dailyinfocopy_mean_copy)
# tavg tmin tmax prcp wdir wspd pres tavgtemp tmintemp tmaxtemp prcptemp wdirtemp wspdtemp prestemp
# 0 21.117.124.8 0.079.0 8.11013.9 19.7333 17.1000 24.8000 0.0000 79.0 8.10001013.9000
# 1 22.819.925.4 0.077.0 9.71013.7 22.8000 19.9000 25.4000 0.0000 77.0 9.70001018.9391
# 2 23.820.926.0 0.076.0 9.71014.4 23.8000 20.9000 26.0000 0.0000 76.0 12.18751018.9391
# 方法二,对控制列逐列填充,其他方法类似
dailyinfocopy_mean_copy2= dailyinfo.copy()
for nancolumnname in dailyinfocopy_mean_copy2.columns[dailyinfocopy_mean_copy2.isna().any()].tolist():
dailyinfocopy_mean_copy2[nancolumnname] = SimpleImputer(missing_values=np.nan, strategy='mean').fit_transform(dailyinfocopy_mean_copy2[[nancolumnname]])
# tavg tmin tmax prcp wdir wspd pres tavgtemp tmintemp tmaxtemp prcptemp wdirtemp wspdtemp prestemp
# time
# 2024-12-0121.117.124.8 0.079.0 8.11013.9 19.7333 17.1000 24.8000 0.0000 79.0 8.10001013.9000
# 2024-12-0222.819.925.4 0.077.0 9.71013.7 22.8000 19.9000 25.4000 0.0000 77.0 9.70001018.9391
# 2024-12-0323.820.926.0 0.076.0 9.71014.4 23.8000 20.9000 26.0000 0.0000 76.0 12.18751018.9391
# 方法三,与方法二类似
dailyinfocopy_mean_copy3= dailyinfo.copy()
nancolumnnames=dailyinfocopy_mean_copy3.columns[dailyinfocopy_mean_copy3.isna().any()].tolist()
dailyinfocopy_mean_copy3[nancolumnnames] = SimpleImputer(missing_values=np.nan, strategy='mean').fit_transform(dailyinfocopy_mean_copy3[nancolumnnames])
# tavg tmin tmax prcp wdir wspd pres tavgtemp tmintemp tmaxtemp prcptemp wdirtemp wspdtemp prestemp
# time
# 2024-12-0121.117.124.8 0.079.0 8.11013.9 19.7333 17.1000 24.8000 0.0000 79.0 8.10001013.9000
# 2024-12-0222.819.925.4 0.077.0 9.71013.7 22.8000 19.9000 25.4000 0.0000 77.0 9.70001018.9391
# 2024-12-0323.820.926.0 0.076.0 9.71014.4 23.8000 20.9000 26.0000 0.0000 76.0 12.18751018.9391
# 中位数填补
dailyinfocopy_median= dailyinfo.copy()
# dailyinfocopy_median = SimpleImputer(missing_values=np.nan, strategy='median').fit_transform(dailyinfocopy)
nancolumnnames=dailyinfocopy_median.columns[dailyinfocopy_median.isna().any()].tolist()
dailyinfocopy_median[nancolumnnames] = SimpleImputer(missing_values=np.nan, strategy='median').fit_transform(dailyinfocopy_median[nancolumnnames])
# 频数填充
dailyinfocopy_most_frequent= dailyinfo.copy()
# dailyinfocopy_most_frequent = SimpleImputer(missing_values=np.nan, strategy='most_frequent').fit_transform(dailyinfocopy)
nancolumnnames=dailyinfocopy_most_frequent.columns[dailyinfocopy_most_frequent.isna().any()].tolist()
dailyinfocopy_most_frequent[nancolumnnames] = SimpleImputer(missing_values=np.nan, strategy='most_frequent').fit_transform(dailyinfocopy_most_frequent[nancolumnnames])
# 常量填充
dailyinfocopy_constant= dailyinfo.copy()
# dailyinfocopy_constant = SimpleImputer(missing_values=np.nan, strategy='constant',fill_value=100).fit_transform(dailyinfocopy)
nancolumnnames=dailyinfocopy_constant.columns[dailyinfocopy_constant.isna().any()].tolist()
dailyinfocopy_constant[nancolumnnames] = SimpleImputer(missing_values=np.nan, strategy='constant',fill_value=0).fit_transform(dailyinfocopy_constant[nancolumnnames])
# ---------------------------------------通过sklearn的KNN近邻法对缺省值进行处理-----------------------------------------
# 最近的3个邻居,使用的是3者的均值
dailyinfocopy_KNN= dailyinfo.copy()
# dailyinfocopy_KNN = KNNImputer(n_neighbors=3).fit_transform(dailyinfocopy)
nancolumnnames=dailyinfocopy_constant.columns[dailyinfocopy_KNN.isna().any()].tolist()
dailyinfocopy_KNN[nancolumnnames] = KNNImputer(n_neighbors=3).fit_transform(dailyinfocopy_KNN[nancolumnnames])
# SimpleImputer(missing_values=np.nan, strategy='median').fit_transform(dailyinfocopy_KNN[nancolumnnames])
第六段代码是基于随机森林来填充,一旦涉及时间列,所有互联网上看到的代码都是会报错的,在这里花了一些时间来处理这些问题。
# ---------------------------------------随机森林对缺省值进行处理-----------------------------------------
# 日期列在随机森林会报错,因此要重置索引后,删除该列
dailyinfocopy= dailyinfo.copy()
dailyinfocopy.reset_index(inplace=True)
del dailyinfocopy[dailyinfocopy.columns[0]]
# 创建一个副本,保存时间列
dailyinfocopywithtime= dailyinfo.copy()
dailyinfocopywithtime.reset_index(inplace=True)
timecolumn=dailyinfocopywithtime['time']
# 创建一个‘target’列,是未空列,作为预测列
dailyinfocopy['target']=1
target=dailyinfocopy['target']
# 获取其他列,不选取刚才加的target列
features = dailyinfocopy.iloc[:, 0:-1]
# 构造随机森林所需的数据集
X_full, y_full = features, target
n_samples = X_full.shape[0] # 样本
n_features = X_full.shape[1] # 特征
X_missing_reg = X_full.copy()
# 获取null列统计
X_df = X_missing_reg.isnull().sum()
# 得出列名 缺失值最少的列名 到 缺失值最多的列名
colname = X_df[~X_df.isin([0])].sort_values().index.values
# colname= ['wdirtemp''prcptemp''tmaxtemp''tavgtemp''wspdtemp''prestemp''tmintemp']
# 缺失值从小到大的特征顺序
sortindex = []
for i in colname:
sortindex.append(X_missing_reg.columns.tolist().index(str(i)))
# sortindex= [11, 10, 9, 7, 12, 13, 8]
# 遍历所有的特征,从缺失最少的开始进行填补,每完成一次回归预测,就将预测值放到原本的特征矩阵中,再继续填补下一个特征
for i in sortindex:
# 构建我们的新特征矩阵和新标签
df = X_missing_reg # 充当中间数据集
fillc = df.iloc[:, i] # 缺失值最少的特征列
# 除了第 i 特征列,剩下的特征列+原有的完整标签 = 新的特征矩阵
df = pd.concat([df.drop(df.columns[i], axis=1), pd.DataFrame(y_full)], axis=1)
# 在新特征矩阵中,对含有缺失值的列,进行0的填补 ,没循环一次,用0填充的列越来越少
df_0 = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0).fit_transform(df)
# 找出训练集和测试集
# 标签
Ytrain = fillc[fillc.notnull()] # 没有缺失的部分,就是 Y_train
Ytest = fillc[fillc.isnull()] # 不是需要Ytest的值,而是Ytest的索引
# 特征矩阵
Xtrain = df_0[Ytrain.index, :]
Xtest = df_0[Ytest.index, :] # 有缺失值的特征情况
rfc = RandomForestRegressor(n_estimators=100) # 实例化
rfc = rfc.fit(Xtrain, Ytrain) # 训练
Ypredict = rfc.predict(Xtest) # 预测结果,就是要填补缺失值的值
# 将填补好的特征返回到我们的原始的特征矩阵中
X_missing_reg.loc[X_missing_reg.iloc[:, i].isnull(), X_missing_reg.columns[i]] = Ypredict
X_missing_reg['time']=timecolumn
X_missing_reg.set_index('time', inplace=True)
dailyinfoRandomForestRegressor=X_missing_reg
# tavg tmin tmax prcp wdir wspd pres tavgtemp tmintemp tmaxtemp prcptemp wdirtemp wspdtemp prestemp
# time
# 2024-12-0121.117.124.8 0.079.0 8.11013.9 21.100 17.100 24.800 0.000 79.00 8.1001013.900
# 2024-12-0222.819.925.4 0.077.0 9.71013.7 22.800 20.287 25.406 0.000 77.00 9.7001013.700
# 2024-12-0323.820.926.0 0.076.0 9.71014.4 23.800 20.900 26.000 0.000 76.00 9.7001014.400
# 2024-12-0423.421.526.6 1.570.011.61014.8 23.400 21.500 26.600 1.500 70.00 11.6001014.800
第七段代码是将之前若干副本中的插入值和实际值进行均方误差计算,最后通过可视化方式呈现出准确率,这里抛掉了一些常量值填充,误差太大,影响最后误差率呈现效果。
metricdata = (
# ('dailyinfo_fillna',dailyinfo_fillna),
# ('dailyinfo_ffill',dailyinfo_ffill),
# ('dailyinfo_bfill',dailyinfo_bfill),
('dailyinfo_mean',dailyinfo_mean),
('dailyinfo_median',dailyinfo_median),
('dailyinfo_mode',dailyinfo_mode),
('dailyinfo_linear',dailyinfo_linear),
('dailyinfo_time',dailyinfo_time),
('dailyinfo_values',dailyinfo_values),
('dailyinfo_nearest',dailyinfo_nearest),
('dailyinfo_slinear',dailyinfo_slinear),
('dailyinfo_quadratic',dailyinfo_quadratic),
('dailyinfo_cubice',dailyinfo_cubice),
('dailyinfo_polynomial',dailyinfo_polynomial),
# ('dailyinfo_barycentric',dailyinfo_barycentric),
('dailyinfo_pchip',dailyinfo_pchip),
('dailyinfo_spline',dailyinfo_spline),
('dailyinfocopy_mean_copy1',dailyinfocopy_mean_copy1),
('dailyinfocopy_mean_copy2',dailyinfocopy_mean_copy2),
('dailyinfocopy_mean_copy3',dailyinfocopy_mean_copy3),
('dailyinfocopy_median',dailyinfocopy_median),
('dailyinfocopy_most_frequent',dailyinfocopy_most_frequent),
# ('dailyinfocopy_constant',dailyinfocopy_constant),
('dailyinfocopy_KNN',dailyinfocopy_KNN),
('dailyinfoRandomForestRegressor',dailyinfoRandomForestRegressor))
# 创建一个空字典,记录各缺失值算法的准确率
targetnames=['wdirtemp','prcptemp' ,'tmaxtemp', 'tavgtemp' ,'wspdtemp' ,'prestemp' ,'tmintemp']
resourcenames=['wdir' ,'prcp', 'tmax' ,'tavg', 'wspd', 'pres', 'tmin']
accuracydict={}
for logicname, logicpandas in metricdata:
accuracy=0
for targetname,resourcename in zip(resourcenames,targetnames):
accuracy += mean_squared_error(logicpandas[resourcename], logicpandas[targetname])
accuracydict[logicname]=accuracy
# print(logicname,':',accuracy)
# accuracydict
# dailyinfo_mean : 36.19240932807212
# dailyinfo_median : 24.932661290322585
# dailyinfo_mode : 54.81419354838708
# dailyinfo_linear : 24.311348566308247
# dailyinfo_time : 24.311348566308247
# dailyinfo_values : 24.311348566308247
# dailyinfo_nearest : 36.24580645161289
# dailyinfo_slinear : 24.31134856630825
# dailyinfo_quadratic : 18.373887784634906
# dailyinfo_cubice : 17.624795757494642
# dailyinfo_polynomial : 18.373887784634906
# dailyinfo_pchip : 23.852328514247336
# dailyinfo_spline : 71.26528378383206
# dailyinfocopy_mean_copy1 : 36.19240932807212
# dailyinfocopy_mean_copy2 : 36.19240932807212
# dailyinfocopy_mean_copy3 : 36.19240932807212
# dailyinfocopy_median : 24.932661290322585
# dailyinfocopy_most_frequent : 54.81419354838708
# dailyinfocopy_KNN : 22.760931899641594
# dailyinfoRandomForestRegressor : 1.619480741935444
plt.figure(figsize=(12, 6))
cmap = plt.cm.viridis # 使用viridis色图
colors = [cmap(i / len(accuracydict)) for i in range(len(accuracydict))] # 为每个条形生成颜色
plt.barh(accuracydict.keys() , accuracydict.values() , color=colors)
plt.show()
我们可以看一下最后的效果,随机森林是最高的,有些意外的是近邻法反而比较低,插值法比平均数、众数还要稍差一些,当然这只是一次的比较而已,也可能时间数据太少的原因。

把时间startdate=datetime(2023,1,1)后,再执行各类方法的准确率又发生了变化。

总的来说,随机森林的效果是最佳的,随着数据量的增加插值法的效果要好于均数、众数、中位数等等。
最后欢迎关注公众号:python与大数据分析

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)