我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

话题回到泰坦尼克数据集,本文以该数据集为例,探讨对数据进行清洗处理的几种方式。对于数据清洗这件事情来说,本文的内容并不是很完整,但是具有代表性。同时,需要注意的是:泰坦尼克数据集也是有很多个版本的,缺失值的情况并不完全一致。

苏南大叔:以泰坦尼克号数据集为例,探讨数据清洗及修复的流程手段 - 泰坦尼克号数据集数据清洗及修复
以泰坦尼克号数据集为例,探讨数据清洗及修复的流程手段(图1-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码经验文章。测试环境:python@3.12.3pandas@2.2.2numpy@1.26.4xlrd@2.0.1openpyxl@3.1.2

加载数据集

数据集不同版本的选择,和后面的代码的编写是很紧密相关的。下面的链接可以对泰坦尼克数据集做较详细的描述。

对于na空值,实际上是本文讨论的重点内容。什么样的数据可以被认为是napandas是有着自己的标准的。但是,这个标准可以被自定义。比如一些不合理的数据,也可以在读取excel文件的时候,通过定义na_values参数,就被自动转化为NA值。

import pandas as pd
file = "http://hbiostat.org/data/repo/titanic3.xls"
df = pd.read_excel(file, "titanic3", index_col=None, na_values=['NA'])

去掉重复值

是否需要去掉重复值,这个就不一定了,看数据集的具体情况而定。对于本文的泰坦尼克数据集来说,这个操作就是不必要的。不过执行一下,也无伤大雅。

df = df.drop_duplicates()

dataframe去重的问题,可以参考文章:

删除不合理值

假如,存在着一些明显不合理的数据,也是可以直接删除的。使用dataframe的条件筛选功能,就可以找到这些数据。

df = df.drop(df[df['age'] <= 5].index)
# print(df)
# print(df.count())

条件筛选的方式写法很多,更多的dataframe的条件筛选问题,待后续文章讨论。

还可以选择删除掉有缺陷的数据,比如某条数据存在着空值,那么这条数据就可以视为有缺陷的数据。当然,缺陷数据可以弥补修复,也可以被删除掉。

df = df.dropna()

更多参数,可以参考文章:

观察数据集

观察的数据目标,主要包括:一共有多少列数据,各个字段中每个字段都有多少NA值。这些NA值就是本文要重点处理的字段。

值得注意的是:read_excel()的时候,是可以通过定义na_values谁是NA,来刻意改变空值的范围的。
print(df.count())

输出:

pclass       1309
survived     1309
name         1309
sex          1309
age          1046
sibsp        1309
parch        1309
ticket       1309
fare         1308
cabin         295
embarked     1307
boat          486
body          121
home.dest     745
dtype: int64

根据输出,可以得出数据。少于计数值1309的字段,都是存在缺失值的。

参考文章:

筛选目标字段

比如name字段,对于泰坦尼克数据集的生存率计算来说,并不重要。就可以对它进行删除。参考文章:

df = df.drop("name", axis=1)
df = df.drop(["cabin", "body"], axis=1)

如果想明确的保留哪些字段的时候,也可以这么操作:

selected_cols = ["survived", "pclass", "sex", "age"]
df = df[selected_cols]

填充空值na

对于存在空值的字段,首先要对其进行统计,获得平均值或者中位数值。平均值mean,填充中位数Median,或者某个经验值。

这里对年龄字段填充中位数值。参考代码:

# print(df.count())
df['age'] = df['age'].fillna(df['age'].median())
# print(df.count())

可以通过代码df.count(),观察age字段的非空值的变化。非空值从1046变成了1309

文字变数字

操作的主要例子就是sex性别字段,male1female0

df['sex2']= df['sex'].map({'female':0, 'male': 1}).astype(int)
# print(df)

输出:

      survived  pclass     sex      age  sex2
0            1       1  female  29.0000     0
1            1       1    male   0.9167     1
2            0       1  female   2.0000     0
3            0       1    male  30.0000     1
4            0       1  female  25.0000     0
...        ...     ...     ...      ...   ...
1304         0       3  female  14.5000     0
1305         0       3  female  28.0000     0
1306         0       3    male  26.5000     1
1307         0       3    male  27.0000     1
1308         0       3    male  29.0000     1

数字范围变文字

这个操作的主要例子是age字段,不同的age有着不同的年龄段范围,并且这个范围又是可定义的。参考文章:

df["age2"] = pd.cut(df.age, [0, 12, 18, 30, 60, 80], labels=['baby', 'juvenile', 'youth', 'midage', 'oldman'])
# print(df)

通过打印df,可以看到ageage2之间存在着一一对应的关系。

      survived  pclass     sex      age      age2
0            1       1  female  29.0000     youth
1            1       1    male   0.9167      baby
2            0       1  female   2.0000      baby
3            0       1    male  30.0000     youth
4            0       1  female  25.0000     youth
...        ...     ...     ...      ...       ...
1304         0       3  female  14.5000  juvenile
1305         0       3  female  28.0000     youth
1306         0       3    male  26.5000     youth
1307         0       3    male  27.0000     youth
1308         0       3    male  29.0000     youth

数字范围变成文字后,通常又接连着groupby分组操作。不过,这就属于数据分析的范畴了,而不是数据清洗修复。留作后续文章讨论。参考文章:

查看dataframe所有数据的方式,可以参考:

小数点问题

这里的age字段有个小数点的问题,可以使用round()方法解决。比如:

df['age'] = df['age'].fillna(df['age'].median()).round(1)
# print(df)

输出:

      survived  pclass     sex   age
0            1       1  female  29.0
1            1       1    male   0.9
2            0       1  female   2.0
3            0       1    male  30.0
4            0       1  female  25.0
...        ...     ...     ...   ...
1304         0       3  female  14.5
1305         0       3  female  28.0
1306         0       3    male  26.5
1307         0       3    male  27.0
1308         0       3    male  29.0

枚举变布尔/哑变量/独热码

经过这么多次的文章总结,大家应该也意识到了:单纯的文字是无法完成机器学习的重任的。必须变成数字或者布尔类型,才能参与后续的机器学习计算。所以,对于一些(伪)枚举类型的字段,也可以变成布尔型。使用的方法就是变成“哑变量”。

df = pd.get_dummies(df, columns=['pclass', 'sex'], drop_first=True)

输出:

      survived      age  pclass_2  pclass_3  sex_male
0            1  29.0000     False     False     False
1            1   0.9167     False     False      True
2            0   2.0000     False     False     False
3            0  30.0000     False     False      True
4            0  25.0000     False     False     False
...        ...      ...       ...       ...       ...
1304         0  14.5000     False      True     False
1305         0      NaN     False      True     False
1306         0  26.5000     False      True      True
1307         0  27.0000     False      True      True
1308         0  29.0000     False      True      True

[1309 rows x 5 columns]

pd.get_dummies()中,

  • columns指的就是要转变的字段。
  • drop_first指的是:被转变完的字段要删除掉第一个。(其实就是减少数据的冗余性)

更多内容,请参考文章:

总结

更多苏南大叔使用python进行数据清洗的内容,请参考:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   python