首页 > 分享 > 数据清洗第2篇章

数据清洗第2篇章

数据清洗是数据分析过程中至关重要的一步,它确保数据的准确性、一致性和完整性。这不仅有助于提高分析结果的可靠性和有效性,还能为算法建模决策提供高质量的数据基础。在进行数据分析和建模的过程中,大量的时间花在数据准备上:加载、清理、转换和重新排列,这样的工作占用了工程师 80% 以上的时间。所以掌握常用的数据清洗方法,将帮助我们能更高效、更高质量完成数据清洗工作。

我们将从易到难来讲述数据清洗系列三篇章,本文为第二篇章:数据转换处理,包括数据映射、数据替换、数据离散化、数据标准化、数据归一化,我们将理论和实践结合,层层递进一步一步掌握缺数据转换的处理方法。

1、数据映射

在对数据进行清洗时,我们经常需要将数据进行分类,例如根据年龄划分为儿童/青年/中年/老年,根据分数划分为不及格/及格/良好/优秀等。在 pandas 中,我们可以使用 map 方法用于对 DataFrame 中的元素进行映射。如下所示,我们使用字典进行配置映射,我们根据姓名-性别配置表,基于 name 映射出 sex 列

import pandas as pd

frame_data = pd.DataFrame({'name': ['tom','paz','leo','tom','leo'],

'age': [11, 10, 10, 11, 12]})

mapping = {'tom':'男', 'paz':'女', 'leo':'男'}

frame_data['sex'] = frame_data['name'].map(mapping)

frame_data

name age sex

0 tom 11 男

1 paz 10 女

2 leo 10 男

3 tom 11 男

4 leo 12 男

当被映射的属性比较多时,单纯的配置表就无法满足我们的需求了。此时,我们可以使用函数进行转换,如下所示,配置表变成映射函数,函数中编写相应的映射逻辑

import pandas as pd

frame_data = pd.DataFrame({'name': ['tom','paz','leo','tom','leo'],

'height': [112, 100, 120, 101, 122]})

def height_type(height):

if height >= 120:

return 'high'

elif height < 110:

return 'low'

else:

return 'middle'

frame_data['type'] = frame_data['height'].map(height_type)

frame_data

name height type

0 tom 112 middle

1 paz 100 low

2 leo 120 high

3 tom 101 low

4 leo 122 high

2、数据替换

在数据预处理中,我们有时候要对数据进行替换处理。此时,我们可以使用 replace 方法用于替换 DataFrame 或 Series 中的特定值。它可以用于替换单个值、列表、字典或使用正则表达式进行复杂的替换。我们可以进行进行简单的单个值替换,如下所示

import pandas as pd

frame_data = pd.DataFrame({'name': ['tom','paz','leo','tom','leo'],

'age': [1, 10, 10, 1, 12]})

frame_data.replace(1, 11)

name age

0 tom 11

1 paz 10

2 leo 10

3 tom 11

4 leo 12

当然我们还可以使用字典配置来进行多行多列的替换

import pandas as pd

frame_data = pd.DataFrame({'name': ['tom','paz','leo','tom','leo'],

'age': [1, 10, 10, 1, 12]})

frame_data.replace({'name': {'paz':'jim'}, 'age': {1:11}})

name age

0 tom 11

1 jim 10

2 leo 10

3 tom 11

4 leo 12

如果有更复杂的替换场景,我们还可以使用正则表达式进行替换

import pandas as pd

frame_data = pd.DataFrame({'name': ['tom','paz','leo','tom','leo'],

'age': [1, 10, 10, 1, 12]})

frame_data.replace(to_replace=r'^t', value='T', regex=True)

name age

0 Tom 1

1 paz 10

2 leo 10

3 Tom 1

4 leo 12

replace 替换默认都是生成一个新的数据,我们如果想直接在原 DataFrame 上进行替换,可以设置 inplace=True 

frame_data.replace(1, 10, inplace=True) 3、数据离散化

在数据预处理中连续值经常需要离散化(也叫分箱)进行分析,在 pandas 中可以使用 cut 进行数据的切分成组

import pandas as pd

series_data = pd.Series([10, 20, 30, 40, 50, 60, 70, 80, 90])

bins = [0, 20, 50, 80, 100]

categories = pd.cut(series_data, bins)

categories

0 (0, 20]

1 (0, 20]

2 (20, 50]

3 (20, 50]

4 (20, 50]

5 (50, 80]

6 (50, 80]

7 (50, 80]

8 (80, 100]

dtype: category

Categories (4, interval[int64, right]): [(0, 20] < (20, 50] < (50, 80] < (80, 100]]

可以看到 pandas 返回的对象是一个特殊的 Categorical 对象,其值为由 pandas.cut 计算出的箱,并且内部包含一个 categories(类别)数组。从结果中可以看到,区间的左边是小括号、右边是中括号,其与数学中的区间符号表示含义一致,小括号表示边是开放的,中括号表示它是封闭的(包括边)。我们可以通过传递 right=False 来改变哪一边是封闭的

pd.cut(series_data, bins, right=False)

0 [0, 20)

1 [20, 50)

2 [20, 50)

3 [20, 50)

4 [50, 80)

5 [50, 80)

6 [50, 80)

7 [80, 100)

8 [80, 100)

dtype: category

Categories (4, interval[int64, left]): [[0, 20) < [20, 50) < [50, 80) < [80, 100)]

如果我们向语义化显示集合,可以通过向 labels 选项传递一个列表或数组来传入自定义的箱名也进行语义化显示

age_groups = ['young', 'middle', 'senior', 'old']

pd.cut(series_data, bins, labels=age_groups)

0 young

1 young

2 middle

3 middle

4 middle

5 senior

6 senior

7 senior

8 old

dtype: category

Categories (4, object): ['young' < 'middle' < 'senior' < 'old']

将数据分箱后,我们经常需要统计相关分箱的数量。此时,我们可以通过 value_counts 方法统计每个箱子中的数量,其默认是按数量从多到少进行

categories.value_counts()

(20, 50] 3

(50, 80] 3

(0, 20] 2

(80, 100] 1

Name: count, dtype: int64

其默认是按数量从多到少进行排序的,如果我们不想进行排序,而是直接按箱子的顺序进行输出,则可以通过设置属性 sort=False 不进行排序

categories.value_counts(sort=False)

(0, 20] 2

(20, 50] 3

(50, 80] 3

(80, 100] 1

Name: count, dtype: int64

如果我们想等量划分每个箱子中的数量,可以在 cut 方法中传入整数(表示箱子数量)来代替显式的箱边,pandas 将根据数据中的最小值和最大值计算出等长的箱

pd.cut(series_data, 4)

0 (9.92, 30.0]

1 (9.92, 30.0]

2 (9.92, 30.0]

3 (30.0, 50.0]

4 (30.0, 50.0]

5 (50.0, 70.0]

6 (50.0, 70.0]

7 (70.0, 90.0]

8 (70.0, 90.0]

dtype: category

Categories (4, interval[float64, right]): [(9.92, 30.0] < (30.0, 50.0] < (50.0, 70.0]

以上介绍了 cut 常用的特性,如果我们想通过样本分位数进行分箱,这时我们就需要使用 qcut 方法,通过定义每个分箱数量的占比,自动进行分箱边界值的划分,如下所示

import pandas as pd

series_data = pd.Series([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])

pd.qcut(series_data, [0, 0.2, 0.5, 0.9, 1])

0 (9.999, 28.0]

1 (9.999, 28.0]

2 (28.0, 55.0]

3 (28.0, 55.0]

4 (28.0, 55.0]

5 (55.0, 91.0]

6 (55.0, 91.0]

7 (55.0, 91.0]

8 (55.0, 91.0]

9 (91.0, 100.0]

dtype: category

Categories (4, interval[float64, right]): [(9.999, 28.0] < (28.0, 55.0] < (55.0, 91.0] < (91.0, 100.0]]

4、数据标准化

在数据预处理中,标准化是常用的技术,标准化是将数据转换为均值为0、标准差为1的分布,常用于需要满足正态分布假设的算法中。

import pandas as pd

data = {'value': [10, 20, 30, 40, 50]}

df = pd.DataFrame(data)

mean = df['value'].mean()

std = df['value'].std()

df['standardized'] = (df['value'] - mean) / std

df

value standardized

0 10 -1.264911

1 20 -0.632456

2 30 0.000000

3 40 0.632456

4 50 1.264911

5、数据归一化

在数据预处理中,归一化是常用的技术,归一化是将数据缩放到一个特定的范围(通常是0到1)。适用于特征值范围差异较大的情况

import pandas as pd

data = {'value': [10, 20, 30, 40, 50]}

df = pd.DataFrame(data)

min_value = df['value'].min()

max_value = df['value'].max()

df['normalized'] = (df['value'] - min_value) / (max_value - min_value)

df

value normalized

0 10 0.00

1 20 0.25

2 30 0.50

3 40 0.75

4 50 1.00

本文,我们详细介绍了在数据清洗中我们可以如何进行数据转换,包括数据映射、数据替换、数据离散化、数据标准化、数据归一化,希望对阅读本文的读者有一定的学习提升和借鉴启发,不足之处也欢迎留言指出。

如果你喜欢本文,欢迎点赞,并且关注我们的微信公众号:Python技术极客,我们会持续更新数据挖掘分析领域的好文章,让大家在数据挖掘分析领域持续精进提升,成为更好的自己!

同时可以扫描以下二维码,加入 Python技术极客 群,在群内与众多业界大牛互动,了解行业发展前沿~

相关知识

数据建模的数据清洗:处理缺失值和噪声
【数据收集与清洗】数据收集的方法与数据清洗的基本技巧
KMeans 与数据清洗:如何处理噪声和缺失值
文本的清洗和标准化:如何处理混乱的数据?
数据挖掘综合
python 清洗数据
python 数据整理与清洗 在水质自动监测数据分析中的应用
Python数据分析项目实例2:使用seaborn分析鸢尾花(Iris)数据集
2019情人节消费大数据什么卖最火?计生用品仅排第2首位还是它!
官宣:2023西湖情五粮液玫瑰婚典七大篇章内容

网址: 数据清洗第2篇章 https://m.huajiangbk.com/newsview1400885.html

所属分类:花卉
上一篇: 叶子灰扑扑的?用这小东西一擦,立
下一篇: 大叶绿萝烂根烂叶怎么办?(已有5