在第一节中,介绍了pandas基础,给了几个用pandas加载和查看数据的例子。
https://juejin.cn/post/7260893255189053498
但在进行真正的数据分析之前,你就会发现其实收集来的数据很多时候并不能直接拿来使用,会出现空值,异常数据和多份数据源存在大小写不一致等问题。因此还需要做一些准备工作,将数据进行预处理,对收集来的数据做一个清洗和整合,本文主要介绍数据清理和整合的内容。
3.数据清洗方法
3.1 数据去重
使用drop_duplicates()
方法可以给数据集去重。该方法可以接受一个或多个列名作为参数,并指定是否保留重复行。
可选参数:
subset: 要去重的列的集合
keep: 保留重复项的规则,是保留第一个还是最后一个
ignore_index:是否重新构建索引
# 创建一个包含重复数据的数据集
>>> data = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie', 'Bob', 'David', 'Alice'],
'Age': [25, 30, 35, 30, 40, 45],
'Country': ['USA', 'Canada', 'USA', 'Canada', 'USA', 'Australia']
})
# 原始数据,其中名为Bob为完全重复数据,名为Alice的为部分重复数据
>>> data
Name Age Country
0 Alice 25 USA
1 Bob 30 Canada
2 Charlie 35 USA
3 Bob 30 Canada
4 David 40 USA
5 Alice 45 Australia
# 删除完全重复的值
>>> data.drop_duplicates()
Name Age Country
0 Alice 25 USA
1 Bob 30 Canada
2 Charlie 35 USA
4 David 40 USA
5 Alice 45 Australia
# 删除特定列重复的值,可以看到默认保留了第一条记录
>>> data.drop_duplicates(subset=['Name'])
Name Age Country
0 Alice 25 USA
1 Bob 30 Canada
2 Charlie 35 USA
4 David 40 USA
# 如果想保留最后一条记录,可以将keep参数指定为last
>>> data.drop_duplicates(subset=['Name'], keep='last')
Name Age Country
2 Charlie 35 USA
3 Bob 30 Canada
4 David 40 USA
5 Alice 45 Australia
# 删除重复数据后希望索引依然保持有序,可以用ignore_index=True
>>> data.drop_duplicates(subset=['Name'], keep='last', ignore_index=True)
Name Age Country
0 Charlie 35 USA
1 Bob 30 Canada
2 David 40 USA
3 Alice 45 Australia
3.2 空值处理
3.2.1 如何判断空值
pandas提供了isna,isnull,notna,notnull等空值判断的函数,实际上isna和isnull,notna和notnull是等价的,可以看到它们分别指向同一个地址。
>>> pd.isna
<function isna at 0x00000269EA52C840>
>>> pd.isnull
<function isna at 0x00000269EA52C840>
>>> pd.notna
<function notna at 0x00000269EA53D7B8>
>>> pd.notnull
<function notna at 0x00000269EA53D7B8>
在用法上以上两个函数返回的是boolean类型的数组。
>>> df1 = pd.DataFrame({'a': ['1', None],'b': ['', 'c'], 'c': [None, None]})
>>> df1.isna()
a b c
0 False False True
1 True False True
>>> df1.isnull()
a b c
0 False False True
1 True False True
另外如果要判断DataFrame是否为空,则可以用empty属性:
>>> df1.empty
False
>>> df2 = pd.DataFrame() # 创建一个空的DataFrame
>>> df2.empty
True
3.2.2 空值填充
空值填充分为,用指定值替换、前向填充、后向填充、平均值填充、中位数填充几种形式,值得注意的是,inplace参数为True时,空值填充直接在原数据集下生效,反之则会生成新的数据集。默认情况下,inplace参数为False。
# 创建一个包含空值的数据集
>>> data = pd.DataFrame({'A': [1, 2, None, 4], 'B': [5, None, 7, 8]})
# 使用fillna() 方法用指定值填充
>>> data0 = data.fillna(0)
>>> data0
A B
0 1.0 5.0
1 2.0 0.0
2 0.0 7.0
3 4.0 8.0
# 使用fillna() 方法将空值向前填充
>>> data1 = data.fillna(method='backfill', limit=1)
>>> data1
A B
0 1.0 5.0
1 2.0 7.0
2 4.0 7.0
3 4.0 8.0
# 使用 fillna() 方法将空值向后填充
>>> data2 = data.fillna(method='backfill', limit=1)
>>> data2
A B
0 1.0 5.0
1 2.0 7.0
2 4.0 7.0
3 4.0 8.0
# 使用 fillna() 方法将空值用平均值填充
>>> data3 = data.fillna(data.mean())
>>> data3
A B
0 1.000000 5.000000
1 2.000000 6.666667
2 2.333333 7.000000
3 4.000000 8.000000
# 使用 fillna() 方法将空值用中位数填充
>>> data4 = data.fillna(data.median())
>>> data4
A B
0 1.0 5.0
1 2.0 7.0
2 2.0 7.0
3 4.0 8.0
# 当inplace=True时,直接在原数据集上完成空值替换
>>> data.fillna(0, inplace=True)
>>> data
A B
0 1.0 5.0
1 2.0 0.0
2 0.0 7.0
3 4.0 8.0
3.2.3 删除空值
用dropna
可以删除数据集的空值,还可以用subset指定要删除的是哪几列的空值。
>>> data = pd.DataFrame({'A': [1, 2, None, 4], 'B': [5, None, 7, 8]})
>>> data
A B
0 1.0 5.0
1 2.0 NaN
2 NaN 7.0
3 4.0 8.0
# 删除所有含有空值的行
>>> data.dropna()
A B
0 1.0 5.0
3 4.0 8.0
# 删除'A'列中所有含有空值的行
data.dropna(subset=['A'])
A B
0 1.0 5.0
1 2.0 NaN
3 4.0 8.0
# subset可以指定多个列,删除'A','B'列中所有含有空值的行
data.dropna(subset=['A', 'B'])
A B
0 1.0 5.0
3 4.0 8.0
3.3 格式转换
一个典型的例子是当一个DataFrame的类型字符型的0-9,为了满足某些运算,必须先将其转换成整形,用astype()方法可以实现这个功能。
>>> data = pd.DataFrame({'A':['1', '2', '3'], 'B':['4', '5', '6']})
>>> data['A']
0 1
1 2
2 3
Name: A, dtype: object
>>> data['A'].astype(int)
0 1
1 2
2 3
Name: A, dtype: int32
更一般地,用apply函数也可以进行格式转换:
>>> data.apply(lambda x: float(x['A']), axis=1)
0 1.0
1 2.0
2 3.0
dtype: float64
4.数据整合
4.1 列整合
4.1.1 重命名列
rename
方法可以给DataFrame的列重命名。
# 基本语法:
# df.rename(columns={'旧列名1': '新列名1', '旧列名2': '新列名2'}, inplace=True)
>>> data = pd.DataFrame({'A':['1', '2', '3'], 'B':['4', '5', '6']})
>>> data.rename(columns={'A':'C', 'B':'D'}, inplace=True)
>>> data
C D
0 1 4
1 2 5
2 3 6
4.1.2 删除列
用drop
方法可以删除某些不需要的列,减少数据集的大小。
>>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
>>> df.drop(axis=1, columns=['B'], inplace=True)
A
0 1
1 2
2 3
4.1.3 重新生成索引
使用reset_index
方法可以来重新生成索引。通过在DataFrame上调用该方法,原先的索引将会被转化为一列数据,并生成一个新的自然数索引。
>>> data = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, index=['a', 'b', 'c'])
>>> data
A B
a 1 4
b 2 5
c 3 6
>>> data.reset_index()
index A B
0 a 1 4
1 b 2 5
2 c 3 6
#如果不想保留index这一列索引,则可以将原有的索引删除
>>> data.reset_index(drop=True)
A B
0 1 4
1 2 5
2 3 6
4.2 数据筛选
在一个数据集中,筛选出满足某些条件的数据,是一个比较常见的场景,数据筛选的写法也很多,以下逐一介绍。
- 用
query
方法实现
# 给定一个数据集,下面的用例中亦采用相同数据集
>>> data = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'Age': [25, 30, 35, 40, 45],
'Country': ['USA', 'Canada', 'USA', 'USA', 'Australia']
})
>>> data
Name Age Country
0 Alice 25 USA
1 Bob 30 Canada
2 Charlie 35 USA
3 David 40 USA
4 Eve 45 Australia
>>> data.query('Age > 30 and Country == "USA"')
Name Age Country
2 Charlie 35 USA
3 David 40 USA
- 用
loc
或者iloc
方法实现
# 用loc()方法实现
>>> condition = (data['Age'] > 30) & (data['Country'] == "USA")
>>> data.loc[condition]
Name Age Country
2 Charlie 35 USA
3 David 40 USA
# 用iloc()方法实现
>>> condition = (data.iloc[:, 1] > 30) & (data.iloc[:, 2] == 'USA')
>>> data.iloc[:, :][condition]
Name Age Country
2 Charlie 35 USA
3 David 40 USA
- 直接用逻辑运算符生成bool数组实现(同
loc
方法)
>>> data[(data['Age'] > 30) & (data['Country'] == "USA")]
Name Age Country
2 Charlie 35 USA
3 David 40 USA
4.3 归并数据集
concat
方法可以将两个数据集合并成一个。
这里讨论的场景是两个列名和数据类型一致的数据集如何归并成一个,如果列名和数据类型不一致,可以参考前面的介绍,对列名和数据类型做相应调整。另外值得说明的是,当列名不一致时,两个数据集可以通过merge()等方法合并成一个数据集,在后续的内容中会继续展开。
>>> data1 = pd.DataFrame({'A': [1, 2], 'B': ['a', 'b']})
>>> data2 = pd.DataFrame({'A': [3, 4], 'C': ['c', 'd']})
# 当列不一致时,归并数据集会生成新的列,并没有达到归并的目的
>>> pd.concat([data1, data2])
A B C
0 1 a NaN
1 2 b NaN
0 3 NaN c
1 4 NaN d
# 调整data2的数据
>>> data2 = pd.DataFrame({'A': [3, 4], 'B': ['c', 'd']})
>>> pd.concat([data1, data2])
A B
0 1 a
1 2 b
0 3 c
1 4 d
# concat完会将保留原来的索引,为了重新生成索引,可以用ignore_index参数。
>>> pd.concat([data1, data2], ignore_index=True)
A B
0 1 a
1 2 b
2 3 c
3 4 d