【Python 数据分析】数据预处理:z-score 标准化、min-max 归一化、数据缺失值处理、数据重复处理

发布时间:2024年01月16日

简述 / 前言

本篇文章分享数据分析中最重要的一个步骤:数据预处理。我们在做数据分析之前,都需要采集很多数据,这些数据可能是从官网下载的,可能是从各个大型数据库网站付费购买的,也有可能是通过爬虫获取数据的(爬取数据时要注意规范,要遵守每个网址给的爬虫君子协议,政府官网尽量别去爬,不能非法爬取公民身份资料等敏感信息!!!)。

【补充】什么是网址给的爬虫君子协议?

  • 进入你要爬取网址的根目录,在其后面加上:/robots.txt,就可以看到这个网址允许你爬取哪些分支下的数据,或者不允许你爬取哪些分支下的数据。
  1. 比如你要爬取知乎的信息,那么其君子协议看:https://www.zhihu.com/robots.txt,可以看到知乎不允许未授权用户爬取任何信息,即我们是不能去爬取知乎数据的。只允许了 Googlebot, Googlebot-Image, Baiduspider-news, Baiduspider, Baiduspider-render, Baiduspider-image, bingbot (截止于2024年1月16日只允许上述指定爬虫爬取数据) 爬取指定目录下的数据~
  2. 又比如看看 CSDN 平台的君子协议:https://www.csdn.net/robots.txt,它不允许任何人爬取的目录如下:
    • User-agent: *
    • Disallow: /scripts
    • Disallow: /public
    • Disallow: /css/
    • Disallow: /images/
    • Disallow: /content/
    • Disallow: /ui/
    • Disallow: /js/
    • Disallow: /scripts/
    • Disallow: /article_preview.html*
    • Disallow: /tag/
    • Disallow: /*?*
    • Disallow: /link/
    • Disallow: /tags/
    • Disallow: /news/
    • Disallow: /xuexi/

不论是从什么方式获取的数据,其数据内容或多或少会存在缺失值数据量纲跨度大(就是同一列数据中,有的数据只是个位数,但有的数据范围到了几十万的级别),所以在做数据分析前,数据预处理是必须要做的,哪怕你的数据可能都很正常(其实只有做了这一步才知道你获得的数据正不正常)。

那么本篇文章将分享最常用的两种数据处理方法:z-score 标准化min-max 归一化,以及数据缺失值处理数据重复处理

1. z-score 标准化

z-score 标准化是基于给定数据(data)的 均值(mean) 和 标准差(std) 进行数据标准化的,其计算公式为:
n e w D a t a = d a t a ? m e a n s t d newData = \frac{data - mean}{std} newData=stddata?mean?

对应的 Python 代码示例:

import numpy as np

data = np.array([[ 1.1,  2, 3  ],
                 [   9, 10, 11 ],
                 [10.9,  5, 0.1]])
# 计算均值
mean = np.mean(data, axis=0)
# 计算标准差
std = np.std(data, axis=0)

print(f"每一列的均值:{mean}\n")
print(f"每一列的标准差:{std}\n")
# 减去均值,除以标准差
newData = (data - mean) / std
print(f"z-score标准化:\n{newData}")

# 查看z-score标准化后的每一列均值 和 标准差
print(f"z-score标准化后的每一列均值:{np.mean(newData, axis=0)}\n")
print(f"z-score标准化后的每一列标准差:{np.std(newData, axis=0)}\n")

输出:

每一列的均值:[7.         5.66666667 4.7       ]

每一列的标准差:[4.24342629 3.29983165 4.60941066]

z-score标准化:
[[-1.39038588 -1.1111678  -0.36881071]
 [ 0.47131725  1.31319831  1.36676909]
 [ 0.91906863 -0.20203051 -0.99795838]]
 
z-score标准化后的每一列均值:[ 0.00000000e+00 -1.01770444e-16 -7.40148683e-17]

z-score标准化后的每一列标准差:[1. 1. 1.]

经过z-score标准化后的数据均值都是0,标准差都是1,当然由于计算机计算精度问题,所以现在看到的均值并不都是0,不过也是非常接近于0了!

看看标准化后的数据是什么样的:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(2024)
data = np.random.rand(100, 2) * 10
x = data[:, 0]
y = data[:, 1]

# 新建figure对象
plt.subplot(121)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("原始数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()

# 计算均值
mean = np.mean(data, axis=0)
# 计算标准差
std = np.std(data, axis=0)
# 减去均值,除以标准差
newData = (data - mean) / std
x = newData[:, 0]
y = newData[:, 1]

# 新建figure对象
plt.subplot(122)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("标准化后的数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()
plt.show()

输出:
请添加图片描述

2. min-max 归一化

min-max 归一化是对给定数据进行线性变换,它是基于给定数据(data)的极大值(max_d)和极小值(min_d)进行数据归一化操作的,计算公式如下:

n e w D a t a = d a t a ? m i n _ d m a x _ d ? m i n _ d newData = \frac{data - min\_d}{max\_d - min\_d} newData=max_d?min_ddata?min_d?

对应的 Python 代码示例:

import numpy as np

data = np.array([[ 1.1,  2, 3  ],
                 [   9, 10, 11 ],
                 [10.9,  5, 0.1]])
# 计算极大值
max_d = np.max(data, axis=0)
# 计算极小值
min_d = np.min(data, axis=0)

print(f"每一列的极大值:{max_d}\n")
print(f"每一列的极小值:{min_d}\n")
# 减去极小值,除以 (极大值 - 极小值)
print(f"min-max标准化:\n{(data - min_d) / (max_d - min_d)}")

输出:

每一列的极大值:[10.9 10.  11. ]

每一列的极小值:[1.1 2.  0.1]

min-max标准化:
[[0.         0.         0.26605505]
 [0.80612245 1.         1.        ]
 [1.         0.375      0.        ]]

看看归一化的数据图像是什么样的:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(2024)
data = np.random.rand(100, 2) * 10
x = data[:, 0]
y = data[:, 1]

# 新建figure对象
plt.subplot(131)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("原始数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()

# 计算极大值
max_d = np.max(data, axis=0)
# 计算极小值
min_d = np.min(data, axis=0)
# 减去均值,除以标准差
newData = (data - min_d) / (max_d - min_d)
x = newData[:, 0]
y = newData[:, 1]

# 新建figure对象
plt.subplot(132)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("归一化后的数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()

# 新建figure对象
plt.subplot(133)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title(f"归一化后的数据\n(放大版)", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.grid()

# wspace 控制子图列间距, hspace 控制子图横间距
plt.subplots_adjust(wspace=0.5, hspace=0)
plt.show()

输出:
请添加图片描述

可以看见所有数据都缩放到 [0, 1] 之间了~

3. 数据缺失值处理

现在要用到一个新的第三方库:pandas,这是数据分析中常用的库。

关键方法:.fillna(value, inplace=True),参数含义如下:

参数含义
value你要将缺失值替换成的值
inplace是否覆盖数据框(默认是:False,不覆盖,生成一个新的数据框)

自行创建一个文件:test.csv,数据如下:
在这里插入图片描述

示例:

import pandas as pd

df = pd.read_csv("test.csv", encoding="utf-8")
print(df)
print()

df['age'].fillna(20, inplace=True)  # 更新age列的NaN为20
df['score'].fillna(0, inplace=True)  # 更新score列的NaN为0
print(df)

输出:

   Unnamed: 0    name   age  score
0           0  senlin   NaN    NaN
1           1     Tom   NaN  100.0
2           2    Mary  18.0   60.0
3           2    Mary  18.0   60.0

   Unnamed: 0    name   age  score
0           0  senlin  20.0    0.0
1           1     Tom  20.0  100.0
2           2    Mary  18.0   60.0
3           2    Mary  18.0   60.0

4. 数据重复处理

关键方法:.drop_duplicates(keep=keep, inplace=True),各参数含义如下:

参数含义
keep保留第一个重复值还是最后一个重复值,可以选:first, last
inplace是否覆盖数据框(默认是:False,不覆盖,生成一个新的数据框)
  1. 示例(保留第一个重复值):

    import pandas as pd
    
    df = pd.read_csv("test.csv", encoding="utf-8")
    print(df)
    print()
    
    df.drop_duplicates(keep='first', inplace=True)
    print(df)
    

    输出:

       Unnamed: 0    name   age  score
    0           0  senlin   NaN    NaN
    1           1     Tom   NaN  100.0
    2           2    Mary  18.0   60.0
    3           2    Mary  18.0   60.0
    
       Unnamed: 0    name   age  score
    0           0  senlin   NaN    NaN
    1           1     Tom   NaN  100.0
    2           2    Mary  18.0   60.0
    
  2. 示例(保留最后一个重复值):

    import pandas as pd
    
    df = pd.read_csv("test.csv", encoding="utf-8")
    print(df)
    print()
    
    df.drop_duplicates(keep='last', inplace=True)
    print(df)
    

    输出:

       Unnamed: 0    name   age  score
    0           0  senlin   NaN    NaN
    1           1     Tom   NaN  100.0
    2           2    Mary  18.0   60.0
    3           2    Mary  18.0   60.0
    
       Unnamed: 0    name   age  score
    0           0  senlin   NaN    NaN
    1           1     Tom   NaN  100.0
    3           2    Mary  18.0   60.0
    
文章来源:https://blog.csdn.net/senlin_6688/article/details/135599356
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。