缺失值
缺失值是事实数据集中的常见问题,解决缺失值是数据预处理的关键步骤。缺失值可能因为各种起因而产生,例如数据的构造和品质、数据输出谬误、传输过程中的数据失落或不残缺的数据收集。这些缺失的值可能会影响机器学习模型的准确性和可靠性,因为它们可能会引入偏差并扭曲后果,有些模型甚至在在短少值的状况下根本无法工作。所以在构建模型之前,适当地解决缺失值是必要的。
本文将展现如何应用三种不同级别的办法解决这些缺失值:
- 高级:删除,均值/中值插补,应用畛域常识进行预计
- 中级:回归插补, K-Nearest neighbors (KNN) 插补
- 高级:链式方程(MICE)的多元插补, MICEforest
查看缺失的值
首先必须查看每个个性中有多少缺失值。作为探索性数据分析的一部分,咱们能够应用以下代码来做到这一点:
导入pandas并在数据集中读取它们,对于上面的示例,咱们将应用葡萄酒品质数据集。
importpandasaspd df=pd.read_csv('Wine_Quality.csv')
而后能够用上面的代码行查看缺失的值。
df.isnull().sum()
能够应用以下办法查看任何个性中蕴含缺失值的行:
df_filtered=df[df.isnull().any(axis=1)] df_filtered.head()
当初咱们能够开始解决这些缺失的值了。
高级办法
最简略的办法是删除行或列(个性)。这通常是在缺失值的百分比十分大或缺失值对剖析或后果没有显著影响时进行的。
删除短少值的行。
df_droprows=df.dropna() df_droprows.isnull().sum()
应用以下办法删除列或个性:
df_dropcols=df.drop(columns=['type', 'fixed acidity', 'citric acid', 'volatile acidity', 'residual sugar', 'chlorides', 'pH', 'sulphates']) df_dropcols.isnull().sum()
通过删除行,咱们最终失去一个更短的数据集。当删除特色时,咱们最终会失去一个残缺的数据集,但会失落某些特色。
print("Shape when dropping rows: ", df_droprows.shape) print("Shape when dropping features: ", df_dropcols.shape)
这两种办法都最间接的办法,而且都会导致失落有价值的数据——所以个别状况下不倡议应用。
均值/中值插补
下一个高级的办法是用特色的平均值或中值替换缺失的值。在这种状况下不会失落特色或行。然而这种办法只能用于数值特色(如果应用平均值,咱们应该确保数据集没有歪斜或蕴含重要的异样值)。
比方上面用均值来计算缺失值:
df=df.fillna(df.mean())
当初让咱们查看其中一个估算值:
df[df.index==86]
如果要用中值,能够应用:
df = df.fillna(df.median()) df[df.index==86]
能够看到这里中值和平均值还是有区别的
众数
与下面的办法一样,该办法用特色的模式或最常见的值替换缺失的值。这种办法能够用于分类特色。
首先,让咱们检查一下是否有一个类别占主导地位。咱们能够通过value_counts办法来实现:
df['type'].value_counts()
能够看到有一个“红色”数量最多。因而能够用上面的形式进行填充:
df['type'] =df['type'].fillna(df['type'].mode())
Scikit-Learn的SimpleImputer类
也能够应用Scikit-learn的SimpleImputer类执行平均值、中值和众数的插补。将策略设置为“mean”,“median”或“most_frequency”即可
df_numeric=df.drop(columns='type') imputer_median=SimpleImputer(strategy='median') imputer_median.fit(df_numeric) df_imputed_median=pd.DataFrame(imputer_median.transform(df_numeric), columns=df_numeric.columns) df_imputed_median.head()
咱们也能够将策略设置为' constant ',并指定' fill_value '来填充一个常量值。
均值/中位数/众数的长处:
- 简略和疾速实现
- 它保留了样本量,并升高了上游剖析(如机器学习模型)的偏差危险。
- 与更简单的办法相比,它的计算成本更低。
毛病:
- 没有阐明数据的可变性或散布,可能会导致估算值不能代表实在值。
- 可能会低估或高估缺失值,特地是在具备极其值或异样值的数据集中。
- 缩小方差和人为夸张相关系数在估算数据集。
- 它假如缺失的值是齐全随机缺失(MCAR),这可能并不总是这样
应用畛域常识进行评估
解决缺失数据的另一种可能办法是应用基于畛域常识或业务规定的预计来替换缺失的值。能够通过征询相干畛域的专家,让他们提供业余的见解,这样可能估算出正当和可信的缺失值。
然而这种办法并不一定在事实中就可能很好的施行,因为咱们须要业余的人士来确保它产生精确和牢靠的估算,然而这样的领域专家并不多。所以咱们这里把它归在高级办法中。
中级办法
还有一些略微高级一些的技术来填充那些缺失的值,咱们将应用预测模型来解决问题。但在此之前须要更好地了解缺失值的性质。
缺失值的类型
在咱们持续应用更高级的技术之前,须要考虑一下在数据集中可能遇到的缺失类型。数据集中有不同类型的缺失,理解缺失类型有助于确定适合的办法。以下是一些常见的类型:
齐全随机缺失( Missing Completely at Random):在这种类型中,缺失的值是齐全随机的,这意味着一个值缺失的概率不依赖于任何察看到的或未察看到的变量。例如,如果一个受访者在考察中不小心跳过了一个问题,这就是MCAR。
随机失落(Missing at Random):在这种类型中,一个值缺失的概率取决于察看到的变量,而不是值自身。例如,如果考察对象不太可能答复敏感问题,但不答复问题的偏向取决于可察看到的变量(如年龄、性别和教育),那么这就是MAR。
非随机失落(Missing Not at Random):在这种类型中,一个值缺失的概率取决于未察看到的变量,包含缺失值值自身。例如,如果抑郁程度较高的个体不太可能报告他们的抑郁程度,而不报告的偏向在数据中是无奈察看到的,那么这就是MNAR。
回归插补
咱们将应用一个回归模型来对那些缺失的值进行有依据的猜想,通过剖析数据集中的其余特色,并应用它们的相关性来填补。
在解决遵循某种模式(MAR或MCAR)的缺失数据时,回归插补特地有用。因为当特色之间存在很强的相关性时,这种办法很无效。
咱们这里将创立一个不蕴含分类特色的数据版本。而后认为每一列的缺失值拟合线性回归模型。这里就须要应用Scikit-learn的线性回归模块。
importpandasaspd fromsklearn.linear_modelimportLinearRegression # Read data df=pd.read_csv('Wine_Quality.csv') # Make sub dataframe with only numeric features df=df.drop(columns='type') # Separate the columns with missing values missing_cols=df.columns[df.isna().any()].tolist() non_missing_cols=list(set(df.columns) -set(missing_cols)) print(missing_cols) # loop over each column with missing values forcolinmissing_cols: # Create a copy of the dataframe without missing values in the current column df_temp=df.dropna(subset=[col] +non_missing_cols) # Split the dataframe into features (X) and target variable (y) X=df_temp[non_missing_cols] y=df_temp[col] # Create and fit a linear regression model lr=LinearRegression() lr.fit(X, y) # Impute missing values in the current column using the fitted model df.loc[df[col].isna(), col] =lr.predict(df.loc[df[col].isna(), non_missing_cols])
回归插补的长处:
- 能够解决大量缺失值。
- 能够保留数据集的统计属性,例如均值、方差和相关系数。
- 能够通过缩小偏差和减少样本量来进步上游剖析(例如机器学习模型)的准确性。
回归插补的毛病:
- 它假如缺失变量和察看到的变量之间存在线性关系。
- 如果缺失值不是随机缺失 (MAR) 或齐全随机缺失 (MCAR),则可能会引入偏差。
- 可能不适用于分类或有序变量。
- 在计算上低廉且耗时,尤其是对于大型数据集。
(KNN) 插补
另一种办法是聚类模型,例如K-最近邻 (KNN) 来预计那些缺失值。这与回归插补相似,只是应用不同的算法来预测缺失值。
importpandasaspd fromsklearn.imputeimportKNNImputer # Read data df=pd.read_csv('Wine_Quality.csv') # Make sub dataframe with only numeric features df=df.drop(columns='type') # create a KNN imputer object imputer=KNNImputer(n_neighbors=5) # impute missing values using KNN df=pd.DataFrame(imputer.fit_transform(df), columns=df.columns)
这里咱们就要介绍一个包fancyimpute,它蕴含了各种插补办法:
pip install fancyimpute
应用的办法如下:
# Import the necessary libraries importnumpyasnp importpandasaspd fromfancyimputeimportKNN # Load the dataset df=pd.read_csv('Wine_Quality.csv') # Drop non-numeric features df=df.drop(columns='type') # Get list of columns with missing values missing_cols=df.columns[df.isna().any()].tolist() # Create an instance of the KNN imputer imputer=KNN() # Fit and transform the imputer to the dataset imputed_array=imputer.fit_transform(df[missing_cols]) # Replace the missing values in the original dataset df[missing_cols] =imputed_array # View the imputed dataset df
KNN 插补的长处:
- 能够捕捉变量之间简单的非线性关系。
- 不对数据的散布或变量之间的相关性做出假如。
- 比简略的插补办法(例如均值或中值插补)更精确,尤其是对于中小型数据集。
毛病:
- 计算上可能很低廉,尤其是对于大型数据集或高维数据。
- 可能对间隔度量的抉择和抉择的最近街坊的数量敏感,这会影响准确性。
- 对于高度歪斜或稠密的数据体现不佳。
高级办法
通过链式方程 (MICE) 进行多元插补
MICE 是一种罕用的估算缺失数据的办法。它的工作原理是将每个缺失值替换为一组基于模型的正当值,该模型思考了数据集中变量之间的关系。
该算法首先依据其余残缺的变量为数据集中的每个变量创立一个预测模型。而后应用相应的预测模型估算每个变量的缺失值。这个过程反复屡次,每一轮插补都应用前一轮的插补值,就如同它们是真的一样,直到达到收敛为止。
而后将多个估算数据集组合起来创立一个最终数据集,其中蕴含所有缺失数据的估算值。MICE 是一种弱小而灵便的办法,能够解决具备许多缺失值和变量之间简单关系的数据集。它已成为许多畛域(包含社会科学、衰弱钻研和环境迷信)中填补缺失数据的风行抉择。
fancyimpute包就蕴含了这个办法的实现,咱们能够间接拿来应用
importnumpyasnp importpandasaspd fromfancyimputeimportIterativeImputer # Read data df=pd.read_csv('Wine_Quality.csv') # Convert type column to category (so that miceforest can handle as a categorical attribute rather than string) df=df.drop(columns='type') # Get list of columns with missing values missing_cols=df.columns[df.isna().any()].tolist() # Create an instance of the MICE algorithm imputer=IterativeImputer() # Fit the imputer to the dataset imputed_array=imputer.fit_transform(df[missing_cols]) # Replace the missing values in the original dataset df[missing_cols] =imputed_array # View the imputed dataset df
这个实现没法对分类变量进行填充,那么对于分类变量怎么办呢?
MICEforest
MICEforest 是 MICE的变体,它应用 lightGBM 算法来插补数据集中的缺失值,这是一个很奇异的想法,对吧。
咱们能够应用 miceforest 包来实现它
pipinstallmiceforest #或 condainstall-cconda-forgemiceforest
应用也很简略:
importpandasaspd importmiceforestasmf # Read data df=pd.read_csv('Wine_Quality.csv') # Convert type column to category (so that miceforest can handle as a categorical attribute rather than string) df['type'] =df['type'].astype('category') # Create an instance of the MICE algorithm imputer=mf.ImputationKernel(data=df, save_all_iterations=True, random_state=42) # Fit the imputer to the dataset. Set number of iterations to 3 imputer.mice(3, verbose=True) # Generate the imputed dataset imputed_df=imputer.complete_data() # View the imputed dataset imputed_df
能够看到,分类变量 'type' 的缺失值曾经被填充了
总结
咱们这里介绍了三个层级的缺失值的解决办法,这三种办法的抉择将取决于数据集、缺失数据的数量和剖析指标。也须要认真思考输出缺失数据对最终后果的潜在影响。解决缺失数据是数据分析中的关键步骤,应用适合的填充办法能够帮忙咱们解锁暗藏在数据中的见解,而从主题专家那里寻求输出并评估输出数据的品质有助于确保后续剖析的有效性。
最初咱们介绍的两个python包的地址,有趣味的能够看看:
https://avoid.overfit.cn/post/803b18d975bc4cdd82aa3026cd405ce8
作者:Honzik Jurza