机器学习 —— 分类预测与集成学习

🌟欢迎来到 我的博客 —— 探索技术的无限可能!


🌟博客的简介(文章目录)

本文使用工具
       Anaconda下载安装与使用
       Jupyter Notebook的使用

本文使用数据集
      机器学习实验所需内容.zip


    从指定的数据源读取数据,对数据进行必要的处理,选取合适的特征,构造分类模型,确定一个人的年收入是否超过50K。
    数据来源:1994年美国人口普查数据库。(原始数据下载地址:https://archive.ics.uci.edu/ml/datasets/Adult )。数据存放在data目录中,其中,adult.data存放训练数据,adult.test存放测试数据。
特征列
age:年龄,整数
workclass:工作性质,字符串,包含少数几种取值,例如:Private、State-gov等
education:教育程度,字符串,包含少数几种取值,例如:Bachelors、Masters等
education_num:受教育年限,整数
maritial_status:婚姻状况,字符串,包含少数几种取值,例如:Never-married、Divorced等
occupation:职业,字符串,包含少数几种取值,例如:Sales、Tech-Support等
relationship:亲戚关系,字符串,包含少数几种取值,例如:Husband、Wife等
race:种族,字符串,包含少数几种取值,例如:White、Black等
sex:性别,字符串,包含少数几种取值,例如:Female, Male
capital_gain:资本收益,浮点数
capital_loss:资本损失,浮点数
hours_per_week:每周工作小时数,浮点数
native_country:原籍,包含少数几种取值,例如:United-States, Mexico等
分类标签列:income

>50K
≤50K

(一)数据探查

        熟悉数据,查看数据结构和数据分布情况

1. 读取数据文件,查看行列信息

        文本(字符串)字段的Dtype属性为"object"

import numpy as np
import pandas as pd
train_data_path = 'adult.txt' # 训练数据
test_data_path = 'adult.test' # 测试数据
train_data = pd.read_csv(train_data_path, header=None) # 训练数据文件中不包含列名
test_data = pd.read_csv(test_data_path, header=None, skiprows=1) # 测试文件中的第一行数据无意义,应跳过(skiprows=1)
# 指定各个列的名称
col_labels = ['age', 'workclass', 'fnlwgt', 'education', 'education_num', 'marital_status',
              'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
              'hours_per_week', 'native_country', 'wage_class']
train_data.columns = col_labels # 赋值给train_data列索引
test_data.columns = col_labels # 赋值给test_data列索引
print(train_data.info())#给出样本数据的相关信息概览 :行数,列数,列索引,列非空值个数,列类型,内存占用

在这里插入图片描述

图1:读取训练和测试数据文件,并查看行列信息

2. 查看数值类型列的数据描述信息

        对于数值类型的列,可以分别查看每列的基本统计信息,例如:数据个数、均值、标准差、极值、四分位数、中位数

print(train_data.describe())#给出样本数据的一些基本的统计量,包括均值,标准差,最大值,最小值,分位数等

在这里插入图片描述

图2:查看数值类型列的数据描述信息

3. 以可视化的方式查看数值类型的取值分布情况

        在上一步骤中,我们可以通过输出的结果看到capital_gain和capital_loss列的极小值、四分位数均为0,而极大值很大,这意味着其数据主要分布在0附近。可以通过分箱统计的方式查看数值分布情况

        直方统计图是很直观的查看数值分布的方法。下面的代码将所有数值分成20个区间,然后统计每个区间中的数据个数

import matplotlib.pyplot as plt
# 用在Jupyter notebook中具体作用是当你调用matplotlib.pyplot的绘图函数plot()进行绘图的时候,或者生成一个figure画布的时候,可以直接在你的python console里面生成图像。效果如下:
%matplotlib inline 

numeric_columns = ['age','fnlwgt','education_num','capital_gain','capital_loss','hours_per_week']

#采用直方统计图按顺序可视化以上六个指标的取值分布情况
#六个图都画在同一个画布中
#每个图都要标注图名(哪个指标的可视化结果)

plt.figure(figsize=(16,12)) # 建立画布,figsize设置画布大小
# 使用for循环numeric_columns列表的长度将六个图都画在同一个画布中(i从0开始)
for i in range(len(numeric_columns)):
    plt.subplot(2,3,i+1) # 建系 plt.subplot(行数、列数、索引数(1开始))
    plt.hist(train_data[numeric_columns[i]],bins=20) # 直方图
    plt.title(numeric_columns[i]) # 设置图像标题
    plt.ylabel("Frequency") # 设置y轴的标签文本
    
plt.savefig("one.png") # 保存图片
plt.show()# 把图像显示出来。

在这里插入图片描述

图3:以可视化的方式查看数值类型的取值分布情况

在这里插入图片描述

图4:one.png

4. 查看文本类型列的取值

        对于文本类型的列,观察文本的取值有哪些

        unique函数用于提取出数据集合中的唯一值

        可以发现,某些列(例如:workclass, occupation,native_country等)包含’?'这样的字符,可视为缺失值。后续应处理此类缺失值

        还可以发现,训练数据的wage_class包括两个值:<=50K 和 >50K 而测试数据的是:<=50K. 和 >50K. 后续应使二者统一

print("训练数据:")
for column in train_data.columns:#循环输出train_data各个列的信息
    #判断文本(字符串)字段的Dtype属性是否为"object"
    if train_data[column].dtype == 'object':
        print(column + "取值为:")
#         unique()方法返回的是去重之后的不同值
        print(train_data[column].unique())#提取数据集合中的唯一值(去除重复的元素)
        print("==========================")
print("=========================================================")
print("测试数据:")
for column in test_data.columns:#循环输出test_data各个列的信息
    #判断文本(字符串)字段的Dtype属性是否为"object"
    if test_data[column].dtype == 'object':
        print(column + "取值为:")
        print(test_data[column].unique())#提取数据集合中的唯一值(去除重复的元素)
        print("==========================")

在这里插入图片描述

图5:查看文本类型列的取值
在这里插入图片描述

图6:查看训练数据文本类型列的取值

在这里插入图片描述

图7:查看测试数据文本类型列的取值

5. 查看文本类型的取值分布情况

text_columns = ['workclass','education','marital_status','occupation','relationship','race','sex','native_country','wage_class']
#采用柱状图,按顺序可视化以上九个指标的取值分布情况(温馨提示,此处需要求和哦)
#九个图都画在同一个画布中
plt.figure(figsize=(22,26)) # 建立画布,figsize设置画布大小
# 使用for循环text_columns列表的长度将九个图都画在同一个画布中(i从0开始)
for i in range(len(text_columns)):
    plt.subplot(5,2,i+1) # 建系 plt.subplot(行数、列数、索引数(1开始))
    value_counts = train_data[text_columns[i]].value_counts()# 先求和
    plt.bar(value_counts.index, value_counts.values)# 再画柱状图
    plt.xticks(rotation=50) # 设置x轴的文本倾斜50度
    plt.title(text_columns[i]) # 设置图像标题
plt.savefig("two.png") # 保存图片
plt.show()# 把图像显示出来。

在这里插入图片描述

图8:查看文本类型的取值分布情况

在这里插入图片描述

图9:two.png

6. 观察某行数据及单个字段

        下面的探查中,发现workclass字段的第一个字符为空格符

        进一步可以发现,所有的文本字段第一个字符均为空格。为便于数据处理,后续应设法将多余的空格去除

# 获取第1行数据
# iloc索引器用于按位置进行基于整数位置的索引或者选择。
print(train_data.iloc[0])
print("==========================")
# 获取第1行第2列
workclass = train_data.iloc[0, 1]
print(workclass)      # 可观察到输出中的第一个字符是空格
print(len(workclass))    # 该长度包括了空格

在这里插入图片描述

图10:观察某行数据及单个字段

7. 分析education取值与wage_class的对应数量关系

print("教育类型取值:")
print(train_data.education.unique())#提取数据集合中的唯一值(去除重复的元素)
# Pandas中的crosstab(交叉表)函数
result = pd.crosstab(index=train_data['wage_class'], columns=train_data['education'], rownames=['wage_class'])#使用交叉表函数,分析education取值与wage_class的对应数量关系
print(result)#输出education取值与wage_class的对应数量关系

在这里插入图片描述

图11:分析education取值与wage_class的对应数量关系

(二)数据清洗

        针对数据探查中发现的一些问题,对数据进行某些修改和调整。

1. 去除所有文本字段首尾的多余空格

        train_data.dtypes属性记录了数据集中所有列的类型信息,包括列下标索引(index)及对应的类型名称

        train_data.dtypes[index]返回指定下标索引的列的类型。此处仅匹配类型为文本字符串(object)的列

        train_data[column_index].str.strip()用于将指定列数据转换成字符串,然后调用strip函数去除首尾空格

# 去除训练数据集字段中多余的空格
# train_data.dtypes属性记录了数据集中所有列的类型信息,包括列下标索引(index)及对应的类型名称
for column_index in train_data.dtypes.index:
    #train_data.dtypes[column_index]返回指定下标索引的列的类型。此处仅匹配类型为文本字符串(object)的列
    if train_data.dtypes[column_index] == 'object':
        # train_data[column_index].str.strip()用于将指定列数据转换成字符串,然后调用strip函数去除首尾空格
        train_data[column_index] = train_data[column_index].str.strip()

# 去除测试数据集字段中多余的空格
# test_data.dtypes属性记录了数据集中所有列的类型信息,包括列下标索引(index)及对应的类型名称
for column_index in test_data.dtypes.index:
    #test_data.dtypes[column_index]返回指定下标索引的列的类型。此处仅匹配类型为文本字符串(object)的列
    if test_data.dtypes[column_index] == 'object':
        # test_data[column_index].str.strip()用于将指定列数据转换成字符串,然后调用strip函数去除首尾空格
        test_data[column_index] = test_data[column_index].str.strip()
        
# 查看结果
workclass = train_data.iloc[0, 1]# 获取train_data第1行第2列
print(workclass)
print(len(workclass))#workclass的长度

在这里插入图片描述

图12:所有文本字段首尾的多余空格

2. 统一分类标签

        和之前一样,训练数据和测试数据的wage_class字段的值应统一

        此处将测试数据集中的标签列更改成与训练数据集的一致,即:去掉原始标签值最后的"."号

# str.strip('.')去掉原始标签值最后的"."号
test_data['wage_class'] = test_data['wage_class'].str.strip('.')
# 查看结果
print(test_data['wage_class'].unique())#提取数据集合中的唯一值(去除重复的元素)

在这里插入图片描述

图13:统一分类标签

3. 处理’?'字段

        对于训练数据集,用’?'标记的字段,视为无效值,本例中直接移除含有无效值的样本行

        对于测试数据集,带’?'的数据,用出现次数最多的值(文本字段)填充

print("原始数据:")
print(train_data['workclass'].unique())#提取数据集合中的唯一值(去除重复的元素)
# replace('?', np.nan)将“?”转为无效值np.nan
# dropna()函数的作用是去除读入的数据中(DataFrame)含有NaN的行
train_data = train_data.replace('?', np.nan).dropna()#将“?”转为无效值,然后删除
print("更改后的数据:")
print(train_data['workclass'].unique())#提取数据集合中的唯一值(去除重复的元素)

在这里插入图片描述

图14:处理’?'字段(将“?”转为无效值,然后删除)

print("测试数据修正前:") #0-10行,并且是workclass,occupation,native_country的数据
print(test_data.loc[:10, ['workclass', 'occupation', 'native_country']])

for column in test_data.columns:
    if test_data[column].dtype == 'object':
#         使用value_counts()方法显示Pandas系列中的最频繁的值
        column_most_common_value = test_data[column].value_counts().index[0]#获取出现次数最多的值
#         replace('?', column_most_common_value)将“?”转为出现次数最多的值(column_most_common_value)
        test_data[column] = test_data[column].replace('?', column_most_common_value)#带'?'的数据,用出现次数最多的值(文本字段)填充

print("测试数据修正后:")#0-10行,并且是workclass,occupation,native_country的数据
print(test_data.loc[:10, ['workclass', 'occupation', 'native_country']])

在这里插入图片描述

图15:处理’?'字段(将“?”转为出现次数最多的值)

(三)数据预处理

        将各个特征转换成模型训练所需要的类型或格式。

1. 文本字段转换成数值字段的方法试验

        workclass的取值是文本类型,但模型训练需要的特征必须是数值,因此需要转换

        通过Categorical函数,可将文本转换成数值。相同的文本值被赋予相同的数值,并且从1,2,3…依次增长

# Categorical函数,将文本转换成数值。相同的文本值被赋予相同的数值,并且从1,2,3...依次增长
workclass_categorical = pd.Categorical(train_data['workclass'])
print(workclass_categorical.codes )

在这里插入图片描述
图16:文本字段转换成数值字段的方法试验

2. 将所有文本列均转换成数值编码

        此处将训练数据和测试数据合并起来进行编码

# merged_data = train_data.append(test_data)    # 合并训练集和测试集
# FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
# 弃用警告,append方法将弃用,建议使用concat方法,而concat是pandas的函数,pandas.concat()通常用来连接DataFrame对象。要写成df=pd.concat([df1,df2])类似这样
# concat()通常用来连接DataFrame对象,默认情况下是对两个DataFrame对象进行纵向连接
merged_data = pd.concat([train_data, test_data]) # 合并训练集和测试集
for column in merged_data.columns:
    if merged_data[column].dtype == 'object':
        merged_data[column] = pd.Categorical(merged_data[column]).codes#Categorical函数,将文本转换成数值。

train_data = merged_data[0:train_data.shape[0]]
test_data = merged_data[train_data.shape[0]:]

print("训练数据维度:", train_data.shape)#.shape返回的是元组
print("测试数据维度:", test_data.shape)
print(test_data.head())#head()默认情况下,它会显示5行系列数据

在这里插入图片描述

图17:将所有文本列均转换成数值编码

(四)模型训练

        训练模型并选择最优的超参数。

1. 准备工作

        准备好训练特征数据集、标签数据集和测试特征数据集、标签数据集

        预设超参数

X_train = train_data.iloc[:, :-1]
y_train = train_data['wage_class']

X_test = test_data.iloc[:, :-1]
y_test = test_data['wage_class']

cv_params = {'max_depth': [3, 5, 7], 'min_child_weight': [1, 3, 5]}
ind_params = {'learning_rate': 0.1, 'n_estimators': 1000, 'seed': 0,
              'subsample': 0.8, 'colsample_bytree': 0.8,
              'objective': 'binary:logistic'}

在这里插入图片描述

图18:准备工作

2. 使用XGBoost模型训练,并且优选出最佳的模型参数

        先固定learning_rate和subsample,以便优选另外两个超参数:max_depth, min_child_weight

from xgboost import XGBClassifier#加载xgboost分类器(封装好的直接用)
from sklearn.model_selection import GridSearchCV#模型调参方法:GridSearch+CV(网格搜索+交叉验证)

print("训练模型并选择最优参数......")
# 使用5-fold cross-validation(5折交叉验证)来优选最佳的模型
optimized_GBM = GridSearchCV(XGBClassifier(**ind_params), cv_params, scoring='accuracy', cv=5, n_jobs=-1, verbose=10)#网格搜索:自动调参
# fit生成规则
optimized_GBM.fit(X_train, y_train)#训练

print("最佳参数:", optimized_GBM.best_params_)
# cv_results_返回模型训练过程所有详细信息  cv交叉验证
means = optimized_GBM.cv_results_['mean_test_score']#输出交叉验证结果 将规则应用于训练集
stds = optimized_GBM.cv_results_['std_test_score']#输出交叉验证结果 将规则应用于测试集

for mean, std, params in zip(means, stds, optimized_GBM.cv_results_['params']):    
    print("%0.5f (+/-%0.05f) for %r" % (mean, std * 2, params))#输出结果

在这里插入图片描述

图19:使用XGBoost模型训练,并且优选出最佳的模型参数

3. 计算模型性能

        针对测试数据进行预测

        分别计算每个类别的精确度、召回率和F1值

from sklearn.metrics import classification_report
# predict()函数是Python中预测函数,常用于预测测试集数据,返回的是样本所属的类别标签。
y_pred = optimized_GBM.predict(X_test)#预测/测试
print(classification_report(y_test, y_pred))

在这里插入图片描述

图20:计算模型性能

4. 再次调整超参数

        在上述最优超参数{‘max_depth’: 3, ‘min_child_weight’: 5},条件下调整learning_rate, 以及subsample并选出最优超参数

cv_params = {'learning_rate': [0.1, 0.05, 0.01], 'subsample': [0.7, 0.8, 0.9]}
ind_params = {'max_depth': 3, 'n_estimators': 1000, 'seed': 0,'min_child_weight': 5, 'colsample_bytree': 0.8, 'objective': 'binary:logistic'}

print("训练模型并选择最优参数......")
# 使用5-fold cross-validation来优选最佳的模型
optimized_GBM = GridSearchCV(XGBClassifier(**ind_params), cv_params, scoring='accuracy', cv=5, n_jobs=-1, verbose=10)#网格搜索:自动调参
optimized_GBM.fit(X_train, y_train)#训练   # fit生成规则

print("最佳参数:", optimized_GBM.best_params_)
# cv_results_返回模型训练过程所有详细信息  cv交叉验证
means = optimized_GBM.cv_results_['mean_test_score']#输出交叉验证结果
stds = optimized_GBM.cv_results_['std_test_score']#输出交叉验证结果

for mean, std, params in zip(means, stds, optimized_GBM.cv_results_['params']):    
    print("%0.5f (+/-%0.05f) for %r" % (mean, std * 2, params))#输出结果

在这里插入图片描述

图21:再次调整超参数

5. 寻找最优的模型训练迭代停止时机

        利用前述选定的最佳参数:{‘max_depth’: 3, ‘min_child_weight’: 5, ‘learning_rate’: 0.05, ‘subsample’: 0.8},构建最优XGBoost模型

        XGBoost模型训练时,如果迭代次数过多会进入过拟合。表现就是随着迭代次数的增加,测试集上的测试误差开始下降;当开始过拟合或者过训练时,测试集上的测试误差开始上升,或者波动

        通过设置early_stopping_rounds可指定停止训练的时机。当测试集上的误差在early_stopping_rounds轮迭代之内都没有降低的话,就停止训练

        通过best_iteration属性可获得最佳的迭代次数

# 构建最优XGBoost模型
ind_params = {'max_depth': 3, 'min_child_weight': 5, 'learning_rate': 0.05, 'subsample': 0.8, 'n_estimators': 1000, 'seed': 0, 'colsample_bytree': 0.8, 'objective': 'binary:logistic'}
eval_set = [(X_test, y_test)]

model = XGBClassifier(**ind_params)
# 通过设置early_stopping_rounds可指定停止训练的时机。当测试集上的误差在early_stopping_rounds轮迭代之内都没有降低的话,就停止训练
result = model.fit(X_train, y_train, early_stopping_rounds=100, eval_metric="error", eval_set=eval_set, verbose=20)#训练
print("最佳迭代次数:", result.best_iteration)#通过best_iteration属性可获得最佳的迭代次数

在这里插入图片描述

图22:寻找最优的模型训练迭代停止时机

6. 计算最终模型的性能

# predict()函数是Python中预测函数,常用于预测测试集数据,返回的是样本所属的类别标签。
y_pred = model.predict(X_test, ntree_limit=result.best_iteration)#预测/测试
print(classification_report(y_test, y_pred))

在这里插入图片描述

图23:计算最终模型的性能

(五)特征分析

        观察某个特征之间的相关关系,调整部分特征。

1. 查看各个特征之间的相关性

        seaborn.heatmap用于绘制数据集中每两个特征(列)之间的相关性热力图

        两个特征相关性数值在-1.0~1.0之间。取1.0时说明最强正相关(例如,该特征与自身肯定是1.0),取-1.0时说明最强负相关(数据变化趋势完全相反)

        在下图中,观察每个方格的颜色。越接近白色,说明该方格对应的两个特征(分别由方格所在的横坐标和纵坐标表示)正相关;越接近黑色,则说明负相关

        具有较强相关性(无论正、负)的两个不同特征,可以考虑在建模时,只选取其中的一个特征参与训练(因为另一个特征的趋势与被选中的特征几乎一致或完全相反,对分类结果的影响也相同);

        在本例中,可观察到sex和relationship的负相关性很强(黑色方格),education和education_num的正相关性也比较强(白色方格),因此可以各保留1个特征

        去掉部分强相关特征后,对建模结果几乎们没有影响,但应该能减少计算量

import seaborn as sns

#绘制数据集中每两个特征(列)之间的相关性热力图
#步骤:创建画布→获取数据(train_data.corr())→绘图→show
# 创建画布
# style must be one of white, dark, whitegrid, darkgrid, ticks
sns.set(style='white')
# 建立画布,figsize设置画布大小
plt.figure(figsize=(10, 8))
# 获取数据并绘制热力图
corr = train_data.corr()
# annot为True时,可设置各个参数,包括大小,颜色,加粗,斜体字等
# cmap:matplotlib的colormap名称或颜色对象
# fmt,格式设置
sns.heatmap(corr, annot=True, cmap='Greens',fmt=".2f")#heatmap将矩形数据绘制为颜色编码矩阵
# 保存图片
plt.savefig("three.png") 
# 显示图像
plt.show()

在这里插入图片描述

图24:查看各个特征之间的相关性

在这里插入图片描述

图25:three.png

2. 去除强相关的冗余特征

        本例中去除education_num,保留education特征;去除relationship,保留sex特征

from xgboost import XGBClassifier
from sklearn.metrics import classification_report

# 指定超参数
ind_params = {'max_depth': 3, 'min_child_weight': 5, 'learning_rate': 0.05, 'subsample': 0.8, 'n_estimators': 1000, 'seed': 0, 'colsample_bytree': 0.8, 'objective': 'binary:logistic'}

# 去除强相关的列
# drop()函数的功能是通过指定的索引或标签名称,也就是行名称或者列名称进行删除数据。
X_train_reduced = X_train.drop(columns = ['education_num','relationship'])#drop删除某一列
X_test_reduced = X_test.drop(columns = ['education_num','relationship'])#drop删除某一列
eval_set = [(X_test_reduced, y_test)]

# 训练模型
model = XGBClassifier(**ind_params)
result = model.fit(X_train_reduced, y_train, early_stopping_rounds=100, eval_metric="error", eval_set=eval_set, verbose=50)#fit训练
print("最佳迭代次数:", result.best_iteration)

# 预测并计算性能
# predict()函数是Python中预测函数,常用于预测测试集数据,返回的是样本所属的类别标签。
y_pred = model.predict(X_test_reduced, ntree_limit=result.best_iteration)#预测/测试
print(classification_report(y_test, y_pred))

在这里插入图片描述

图26:去除强相关的冗余特征

在这里插入图片描述

图27:去除强相关的冗余特征结果

3. 将age特征分箱处理

        考虑到age(年龄)是连续的自然数值,在一定程度上,考虑年龄区间可能会比年龄值本身更有意义

        numpy.digitize方法用于将数据集划分到指定的区间中,并重新赋给区间编号值

# 定义年龄区间
age_bins = [20, 30, 40, 50, 60, 70]    # 区间0:0~20,区间1:20~30,......区间6:70~

# 将'age'转换成区间
# digitize()主要用于将一组数据进行分区
X_train_reduced['age'] = np.digitize(X_train['age'], bins=age_bins)#返回每个值属于bins的索引
X_test_reduced['age'] = np.digitize(X_test['age'], bins=age_bins)#返回每个值属于bins的索引
print(X_train_reduced['age'].unique())#提取数据集合中的唯一值(去除重复的元素)
eval_set = [(X_test_reduced, y_test)]

# 指定超参数
ind_params = {'max_depth': 3, 'min_child_weight': 5, 'learning_rate': 0.05, 'subsample': 0.8, 'n_estimators': 1000, 'seed': 0, 'colsample_bytree': 0.8, 'objective': 'binary:logistic'}

# 训练模型
model = XGBClassifier(**ind_params)
result = model.fit(X_train_reduced, y_train, early_stopping_rounds=100, eval_metric="error", eval_set=eval_set, verbose=20)#fit训练
print("最佳迭代次数:", result.best_iteration)

# 预测并计算性能
# predict()函数是Python中预测函数,常用于预测测试集数据,返回的是样本所属的类别标签。
y_pred = model.predict(X_test_reduced, ntree_limit=result.best_iteration)#测试/预测
print(classification_report(y_test, y_pred))

在这里插入图片描述

图28:将age特征分箱处理

在这里插入图片描述

图29:将age特征分箱处理结果

异常问题与解决方案

异常问题1:No module named ‘xgboost’
解决方法:%pip install xgboost
在这里插入图片描述

图30:解决方法

异常问题2:不知crosstab(交叉表)函数如何使用
在这里插入图片描述

图31:异常问题2

解决方法:两种方法解决
在这里插入图片描述

图32:解决方法

参考资料

[1] .iloc和.loc区别、联系与用法
[2] Pandas经典用法:数据筛选之iloc和loc
[3] Pandas中的info()函数与describe()函数
[4] Python pandas.unique用法及代码示例
[5] pandas中concat()的用法
[6] Pandas: 交叉表(crosstab)和透视表(pivot_table)的用法
[7] seaborn.heatmap参数介绍


回到文章开头

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZShiJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值