在数据分析当中,我们通常使用 Pandas 来做数据清理的工作。在真实的工作生活中,我们拿到的数据往往都是不整洁的,空值、重复值、无效值等等信息都会干扰我们的分析,此时我们就需要按部就班的完成数据的清理。数据清理是数据分析中非常重要的一步,也是非常繁琐的一步,当然,在你掌握了 Pandas 库之后,你就好像是得到了一把削铁如泥的宝剑,数据清理工作的效率会大大提高。
Pandas 主要有两种数据结构,分别是 Series 和 DataFrame,他们分别表示一维的序列和二维的表结构。
维数 | 名称 | 描述 |
---|---|---|
1 | Series | 可以看做有标签(默认是整数序列 RangeIndex;可以重复)的一维数组(同类型)。是 scalars(标量) 的集合,同时也是 DataFrame 的元素。 |
2 | DataFrame | 一般是二维标签,尺寸可变的表格结构,具有潜在的异质型列。 |
Series 是一个定长的字典序列。它相当于是两个 ndarray,一个代表 index,一个代表 values。
import pandas as pd
s = pd.Series(data, index=index)
此处的 data,可以是如下的数据类型:
Python 中的 dict
一个 ndarray
一个标量,比如:4
而 index 的默认值是 0,1,2… 递增的整数序列。
指定 index
s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
print(s)
>>>
a -0.595567
b -0.201314
c 1.516812
d 0.102395
e -1.009924
dtype: float64
不指定 index
s1 = pd.Series(['a', 'b', 'c', 'd'])
print(s1)
>>>
0 a
1 b
2 c
3 d
dtype: object
通过字典来创建 Series
d= {'a': 1, 'b': 2, 'c': 3}
s2 = pd.Series(d)
print(s2)
>>>
a 1
b 2
c 3
dtype: int64
DataFrame 是一个二维的数据结构,可以把它理解为数据表格或者是 SQL 表,或者是由 Series 对象组成的字典。
d = {"Chinese": [80, 85, 90], "Math": [85, 70, 95], "English": [90, 95, 90]}
df1 = pd.DataFrame(d)
print(df1)
df2 = pd.DataFrame(d, index=['zhangsan', 'lisi', 'wangwu'])
print(df2)
print(df2.columns, df2.index)
>>>
Chinese Math English
0 80 85 90
1 85 70 95
2 90 95 90
Chinese Math English
zhangsan 80 85 90
lisi 85 70 95
wangwu 90 95 90
Index(['Chinese', 'Math', 'English'], dtype='object') Index(['zhangsan', 'lisi', 'wangwu'], dtype='object')
通过 index 选择 DataFrame 中的数据
操作 | 语法 | 结果类型 |
---|---|---|
选择某一列 | df[col] | Series |
通过标签选择某一行 | df.loc[label] | Series |
通过标签位置选择某一行 | df.iloc[loc] | Series |
切片获取某些行 | df[5:10] | DataFrame |
通过布尔向量获取某些行 | df[bool_vec] | DataFrame |
代码
print(df2['Chinese'], '\n')
print(df2.loc['zhangsan'], '\n')
print(df2.iloc[-1], '\n')
print(df2[0:2], '\n')
print(df2[df2>85], '\n')
>>>
zhangsan 80
lisi 85
wangwu 90
Name: Chinese, dtype: int64 Chinese 80
Math 85
English 90
Name: zhangsan, dtype: int64 Chinese 90
Math 95
English 90
Name: wangwu, dtype: int64 Chinese Math English
zhangsan 80 85 90
lisi 85 70 95 Chinese Math English
zhangsan NaN NaN 90
lisi NaN NaN 95
wangwu 90.0 95.0 90
读取数据
df = pd.read_csv("test.csv")
print(df.head())
print('\n')
print(type(df))
>>>
name age score
0 zhangsan 30.0 80.0
1 lisi 20.0 NaN
2 wangwu 25.0 100000.0
3 zhaoliu NaN 32.0
4 maqi 33.0 60.0
保存数据
df.to_csv('my.csv')
df.to_excel('my.xlsx')
print(df.index, '\n')
print(df.columns, '\n')
print(df.to_numpy(), '\n')
print(df.describe())
>>>
RangeIndex(start=0, stop=5, step=1) Index(['name', 'age', 'score'], dtype='object') [['zhangsan' 30.0 80.0]
['lisi' 20.0 nan]
['wangwu' 25.0 100000.0]
['zhaoliu' nan 32.0]
['maqi' 33.0 60.0]] age score
count 4.000000 4.000000
mean 27.000000 25043.000000
std 5.715476 49971.337211
min 20.000000 32.000000
25% 23.750000 53.000000
50% 27.500000 70.000000
75% 30.750000 25060.000000
max 33.000000 100000.000000
describe 是非常常用的函数,可以通过它来在整体上查看数据的全貌,有助于了解数据。
按轴排序
print(df.sort_index(axis=1, ascending=False))
>>>
score name age
0 80.0 zhangsan 30.0
1 NaN lisi 20.0
2 100000.0 wangwu 25.0
3 32.0 zhaoliu NaN
4 60.0 maqi 33.0
按数值排序
print(df.sort_values(by='score'))
>>>
name age score
3 zhaoliu NaN 32.0
4 maqi 33.0 60.0
0 zhangsan 30.0 80.0
2 wangwu 25.0 100000.0
1 lisi 20.0 NaN
查看缺失值
print(df.isnull(),'\n')
print(df.isnull().any())
>>>
name age score
0 False False False
1 False False True
2 False False False
3 False True False
4 False False False name False
age True
score True
dtype: bool
可以方便的看出数据中,哪些列是存在空值的。
删除/填充空值
df1 = df.copy()
print(df1, '\n')
print(df1.dropna(how='any'), '\n')
print(df1.fillna(value=50))
>>>
name age score
0 zhangsan 30.0 80.0
1 lisi 20.0 NaN
2 wangwu 25.0 100000.0
3 zhaoliu NaN 32.0
4 maqi 33.0 60.0 name age score
0 zhangsan 30.0 80.0
2 wangwu 25.0 100000.0
4 maqi 33.0 60.0 name age score
0 zhangsan 30.0 80.0
1 lisi 20.0 50.0
2 wangwu 25.0 100000.0
3 zhaoliu 50.0 32.0
4 maqi 33.0 60.0
重命名列
df1.rename(columns={'name': 'student'}, inplace = True)
print(df1)
>>>
student age score
0 zhangsan 30.0 80.0
1 lisi 20.0 NaN
2 wangwu 25.0 100000.0
3 zhaoliu NaN 32.0
4 maqi 33.0 60.0
删除列/行
df1 = df1.drop(columns=['age'])
print(df1, '\n')
df1 = df1.drop(index=[1])
print(df1)
>>>
student score
0 zhangsan 80.0
1 lisi NaN
2 wangwu 100000.0
3 zhaoliu 32.0
4 maqi 60.0 student score
0 zhangsan 80.0
2 wangwu 100000.0
3 zhaoliu 32.0
4 maqi 60.0
去除重复值
df = df.drop_duplicates() # 去除重复行
修改数据格式
df1['score'].astype('str')
apply 函数的应用
apply 用来将函数应用到数据上。
df2 = df1['score'].apply(lambda x: x * 2)
print(df2)
>>>
0 160.0
2 200000.0
3 64.0
4 120.0
Name: score, dtype: float64
以上代码等价于
list(map(lambda x: x*2, df1['score']))
>>>
[160.0, 200000.0, 64.0, 120.0]
由此可以看出,apply 是一个高效且简洁的函数,可以快速把函数作用到每个元素之上。
直方图化
所谓的直方图化,就是函数 value_counts,该函数可以查看数据中,每列中有多少不同值,且各个不同值出现的次数
print(df, '\n')
df3 = df.fillna(60)
df3.loc[5] = ['qianba', 20, 80] # 新增一行
print(df3['score'].value_counts())
>>>
name age score
0 zhangsan 30.0 80.0
1 lisi 20.0 NaN
2 wangwu 25.0 100000.0
3 zhaoliu NaN 32.0
4 maqi 33.0 60.0 60.0 2
80.0 2
32.0 1
100000.0 1
Name: score, dtype: int64
合并
1、使用 concat 连接两个 Pandas 对象
print(df3, '\n')
df4 = df3.copy()
df3 = pd.concat([df3, df4], ignore_index=True)
print(df3)
>>>
name age score
0 zhangsan 30.0 80.0
1 lisi 20.0 60.0
2 wangwu 25.0 100000.0
3 zhaoliu 60.0 32.0
4 maqi 33.0 60.0
5 qianba 20.0 80.0 name age score
0 zhangsan 30.0 80.0
1 lisi 20.0 60.0
2 wangwu 25.0 100000.0
3 zhaoliu 60.0 32.0
4 maqi 33.0 60.0
5 qianba 20.0 80.0
6 zhangsan 30.0 80.0
7 lisi 20.0 60.0
8 wangwu 25.0 100000.0
9 zhaoliu 60.0 32.0
10 maqi 33.0 60.0
11 qianba 20.0 80.0
2、使用 merge 函数
基于某一列进行连接
left = pd.DataFrame({'key': ['foo', 'bar', 'loo'], 'lval': [1, 2, 3]})
right = pd.DataFrame({'key': ['foo', 'bar', 'roo'], 'rval': [3, 4, 5]})
print(left, '\n')
print(right, '\n')
print(pd.merge(left, right, on='key'))
>>>
key lval
0 foo 1
1 bar 2
2 loo 3
key rval
0 foo 3
1 bar 4
2 roo 5
key lval rval
0 foo 1 3
1 bar 2 4
内连接(innert),取键的交集
print(pd.merge(left, right, how='inner'))
>>>
key lval rval
0 foo 1 3
1 bar 2 4
还有左连接、右连接和外连接,你可以自己尝试下,看看有什么区别。
分组
所谓的分组,就是根据一些标准,将数据分解成一些组,将函数独立的应用到每个组上,最后将结果组合成数据结构。
df = pd.DataFrame({'A': ['foo', 'bar', 'bar', 'foo', 'foo', 'foo'],
'B': ['one', 'two', 'three', 'one', 'two', 'two'],
'C':[1, 2, 3, 4, 5, 6]})
print(df, '\n')
print(df.groupby('A').sum(), '\n')
print(df.groupby('B').sum())
>>>
A B C
0 foo one 1
1 bar two 2
2 bar three 3
3 foo one 4
4 foo two 5
5 foo two 6 C
A
bar 5
foo 16 C
B
one 5
three 3
two 13
也可以按照多列分组
print(df.groupby(['A', 'B']).sum())
>>>
C
A B
bar three 3
two 2
foo one 5
two 11
Pandas 同样提供绘制图表的功能
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2018', periods=1000))
print(ts, '\n')
ts = ts.cumsum() # 返回累计值
ts.plot()
>>>
2018-01-01 1.055229
2018-01-02 0.101467
2018-01-03 -2.083537
2018-01-04 1.178102
2018-01-05 -0.084247
...
2020-09-22 -4.316770
2020-09-23 -0.823494
2020-09-24 0.215199
2020-09-25 1.094516
2020-09-26 0.285788
Freq: D, Length: 1000, dtype: float64 Out[94]:
图片