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

数据分析师必备:数据预处理方法详解-z-score标准化、min-max归一化及缺失值、重复值处理
本文介绍了数据分析中的重要步骤——数据预处理,包括z-score标准化、min-max归一化,以及如何处理数据中的缺失值和重复值,以确保数据质量。使用Pandas库的示例代码展示了这些技术在实际应用中的操作。

简述 / 前言

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

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

  • 进入你要爬取网址的根目录,在其后面加上:/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=stddatamean

对应的 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_dmin_ddatamin_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
    
<think>好的,用户想了解数据预处理的方法及其实现方式,具体包括缺失值处理、异常值处理数据归一化,并希望有示例代码或教程。我需要根据提供的引用内容来组织回答,确保覆盖各个部分,同时正确使用格式和引用标注。 首先,我需要整理数据预处理的各个部分。根据用户的问题,分为缺失值处理、异常值处理数据归一化。每个部分需要对应的方法和实现方式,结合引用中的信息。 缺失值处理方面,引用[1]提到删除法和视为缺失值处理,引用[3]有删除重复值的代码,但可能需要调整。引用[4]中的抽样方法可能不直接相关,但其他方法如中位数填充可以参考引用[2]中的替换异常值的方法,比如用均值、中位数填充缺失值。 异常值处理,引用[1]详细说明了删除记录、视为缺失值、平均值修正和不处理。引用[2]补充了替换异常值的方法,如使用统计量或插值法。需要将这些方法分类为删除法、替代法、修正法,并对应引用[1]和[2]。 数据归一化部分,用户提到了Min-Max和Z-Score,虽然引用中没有直接提到,但引用[2]提到了标准化归一化,可以结合这些信息展开。可能需要补充相关知识,确保正确性。 示例代码方面,引用[3]提供了删除重复值的代码,可以调整用于缺失值处理的删除法。引用[2]中的替换异常值可以用Pandas的fillna方法。归一化部分可能需要使用Scikit-learn的MinMaxScaler和StandardScaler,虽然引用中没有提到,但这是常见方法,可以合理添加,并确保代码正确。 需要确保每个步骤都有对应的引用标注,例如缺失值处理的删除法引用[1],替代法引用[2]等。同时注意用户要求行内数学公式用$...$,独立公式用$$...$$。例如,Z-Score的公式应单独成段。 最后,生成相关问题,可能需要围绕数据预处理的各个步骤,如不同归一化方法的比较、处理缺失值的其他方法、异常值检测方法等。确保问题相关且基于回答内容。 检查所有引用是否正确对应,例如修正法对应引用[1]的平均值修正,替代法对应引用[2]的替换异常值。代码示例需要正确使用Pandas和Scikit-learn库,并符合语法规范。 现在组织内容,分章节撰写,确保结构清晰,引用正确,代码示例无误,数学公式格式正确,最后生成相关问题。</think>### 数据预处理方法总结 #### 一、缺失值处理 1. **删除法** 直接删除含有缺失值的行或列,适用于缺失比例较高或对分析影响较小的情况。 ```python data.dropna(axis=0, how='any', inplace=True) # 删除含缺失值的行 ``` 2. **中位数/均值填充** 用特征列的均值或中位数填充缺失值,适用于数值型数据。 ```python data['列名'].fillna(data['列名'].median(), inplace=True) # 中位数填充 data['列名'].fillna(data['列名'].mean(), inplace=True) # 均值填充 ``` #### 二、异常值处理 1. **删除法** 直接删除异常值记录,适用于异常值较少且对模型影响显著的情况[^1]。 ```python q_low = data['列名'].quantile(0.01) # 1%分位数 q_high = data['列名'].quantile(0.99) # 99%分位数 data = data[(data['列名'] > q_low) & (data['列名'] < q_high)] ``` 2. **替代法** 用均值、中位数或插值法替换异常值,保持数据分布特征[^2]。 ```python data.loc[data['列名'] > 阈值, '列名'] = data['列名'].median() # 中位数替代 ``` 3. **修正法** 使用前后观测值的平均值修正异常值,适用于时间序列数据。 ```python data['列名'] = data['列名'].interpolate(method='linear') # 线性插值 ``` #### 三、数据归一化 1. **Min-Max 归一化** 将数据缩放到 $[0,1]$ 区间,公式为: $$x_{\text{norm}} = \frac{x - x_{\min}}{x_{\max} - x_{\min}}$$ ```python from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() data_scaled = scaler.fit_transform(data) ``` 2. **Z-Score 标准化** 将数据转换为均值为 0、标准差为 1 的分布,公式为: $$x_{\text{std}} = \frac{x - \mu}{\sigma}$$ ```python from sklearn.preprocessing import StandardScaler scaler = StandardScaler() data_standardized = scaler.fit_transform(data) ``` #### 四、其他方法 - **数据去重**:删除重复记录[^3] ```python data.drop_duplicates(subset=["列名"], keep='first', inplace=True) ``` - **数据归约**:通过抽样或聚类减少数据规模[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值