Pandas 百题大冲关
实验介绍
Pandas 是基于 NumPy 的一种数据处理工具,该工具为了解决数据分析任务而创建。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的函数和方法。
Pandas 的数据结构:Pandas 主要有 Series(一维数组),DataFrame(二维数组),Panel(三维数组),Panel4D(四维数组),PanelND(更多维数组)等数据结构。其中 Series 和 DataFrame 应用的最为广泛。
- Series 是一维带标签的数组,它可以包含任何数据类型。包括整数,字符串,浮点数,Python 对象等。Series 可以通过标签来定位。
- DataFrame 是二维的带标签的数据结构。我们可以通过标签来定位数据。这是 NumPy 所没有的。
Pandas 百题大冲关分为基础篇和进阶篇,每部分各有 50 道练习题。基础部分的练习题在于熟悉 Pandas 常用方法的使用,而进阶部分则侧重于 Pandas 方法的组合应用。
如果你在学习课程之前已经有 Pandas 使用基础,那么可以对照着单元格复习一遍。如果你对 Pandas 并不熟练,就一定要亲自动手在每个示例单元格下方的空白单元格中练习。
实验知识点
本次实验涉及的知识点主要有:
- 创建Series
- Series基本操作
- 创建DataFrame
- DataFrame基本操作
- DataFrame文件操作
- Series,DataFrame和多索引
- 透视表
- 数据清洗
- 数据预处理
- 可视化
实验环境
- Python 3.6
- NumPy
- Pandas
目录索引
1. 基础部分
导入 Pandas 模块
1. 导入 Pandas
练习 Pandas 之前,首先需要导入 Pandas 模块,并约定简称为 pd
。
import pandas as pd
# 在空白单元格中重复输入上面的代码练习,亲自动手,不要复制粘贴哦!
2. 查看 Pandas 版本信息
print(pd.__version__)
创建 Series 数据类型
Pandas 中,Series 可以被看作由 1 列数据组成的数据集。
创建 Series 语法:s = pd.Series(data, index=index)
,可以通过多种方式进行创建,以下介绍了 3 个常用方法。
3. 从列表创建 Series
arr=[0, 1, 2, 3, 4]
s1=pd.Series(arr) # 如果不指定索引,则默认从 0 开始
s1
0 0
1 1
2 2
3 3
4 4
dtype: int64
提示:前面的 0,1,2,3,4
为当前 Series 的索引,后面的 0,1,2,3,4
为 Series 的值。
4. 从 Ndarray 创建 Series
import numpy as np
n=np.random.randn(5) # 创建一个随机 Ndarray 数组
index=['a','b','c','d','e']
s2=pd.Series(n,index=index)
s2
a -0.991378
b -0.326034
c 0.079687
d -0.149198
e -1.318138
dtype: float64
5. 从字典创建 Series
d={'a':1,'b':2,'c':3,'d':4,'e':5}
s3=pd.Series(d)
s3
a 1
b 2
c 3
d 4
e 5
dtype: int64
Series 基本操作
6. 修改 Series 索引
print(s1) # 以 s1 为例
s1.index=['A','B','C','D','E'] # 修改后的索引
s1
0 0
1 1
2 2
3 3
4 4
dtype: int64
A 0
B 1
C 2
D 3
E 4
dtype: int64
7. Series 纵向拼接
s4=s3.append(s1) # 将 s1 拼接到 s3
s4
a 1
b 2
c 3
d 4
e 5
A 0
B 1
C 2
D 3
E 4
dtype: int64
8. Series 按指定索引删除元素
print(s4)
s4=s4.drop('e') # 删除索引为 e 的值
s4
a 1
b 2
c 3
d 4
e 5
A 0
B 1
C 2
D 3
E 4
dtype: int64
a 1
b 2
c 3
d 4
A 0
B 1
C 2
D 3
E 4
dtype: int64
9. Series 修改指定索引元素
s4['A']=6 # 修改索引为 A 的值 = 6
s4
a 1
b 2
c 3
d 4
A 6
B 1
C 2
D 3
E 4
dtype: int64
10. Series 按指定索引查找元素
s4['B']
1
11. Series 切片操作
例如对s4
的前 3 个数据访问
s4[:3]
a 1
b 2
c 3
dtype: int64
Series 运算
12. Series 加法运算
Series 的加法运算是按照索引计算,如果索引不同则填充为 NaN
(空值)。
s4.add(s3)
A NaN
B NaN
C NaN
D NaN
E NaN
a 2.0
b 4.0
c 6.0
d 8.0
e NaN
dtype: float64
13. Series 减法运算
Series的减法运算是按照索引对应计算,如果不同则填充为 NaN
(空值)。
s4.sub(s3)
A NaN
B NaN
C NaN
D NaN
E NaN
a 0.0
b 0.0
c 0.0
d 0.0
e NaN
dtype: float64
14. Series 乘法运算
Series 的乘法运算是按照索引对应计算,如果索引不同则填充为 NaN
(空值)。
s4.mul(s3)
A NaN
B NaN
C NaN
D NaN
E NaN
a 1.0
b 4.0
c 9.0
d 16.0
e NaN
dtype: float64
15. Series 除法运算
Series 的除法运算是按照索引对应计算,如果索引不同则填充为 NaN
(空值)。
s4.div(s3)
A NaN
B NaN
C NaN
D NaN
E NaN
a 1.0
b 1.0
c 1.0
d 1.0
e NaN
dtype: float64
16. Series 求中位数
s4.median()
3.0
17. Series 求和
s4.sum()
26
18. Series 求最大值
s4.max()
6
19. Series 求最小值
s4.min()
1
创建 DataFrame 数据类型
与 Sereis 不同,DataFrame 可以存在多列数据。一般情况下,DataFrame 也更加常用。
20. 通过 NumPy 数组创建 DataFrame
dates=pd.date_range('today',periods=6) # 定义时间序列作为 index
num_arr=np.random.randn(6,4) # 传入 numpy 随机数组
columns=['A','B','C','D'] # 将列表作为列名
df1=pd.DataFrame(num_arr,index=dates,columns=columns)
df1
A | B | C | D | |
---|---|---|---|---|
2018-04-17 01:12:38.805877 | 0.848962 | -0.377572 | 2.124144 | 0.794958 |
2018-04-18 01:12:38.805877 | -0.920862 | 0.201444 | -0.590866 | 0.902380 |
2018-04-19 01:12:38.805877 | 0.965119 | 0.016123 | -0.799221 | 0.345228 |
2018-04-20 01:12:38.805877 | -0.339873 | -0.580011 | -0.337110 | -1.262724 |
2018-04-21 01:12:38.805877 | -0.184359 | 0.215222 | -0.878790 | -0.216809 |
2018-04-22 01:12:38.805877 | -0.223707 | -0.179329 | -0.794284 | -1.555711 |
21. 通过字典数组创建 DataFrame
data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'],
'age': [2.5, 3, 0.5, np.nan, 5, 2, 4.5, np.nan, 7, 3],
'visits': [1, 3, 2, 3, 2, 3, 1, 1, 2, 1],
'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']}
labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
df2 = pd.DataFrame(data, index=labels)
df2
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
a | 2.5 | cat | yes | 1 |
b | 3.0 | cat | yes | 3 |
c | 0.5 | snake | no | 2 |
d | NaN | dog | yes | 3 |
e | 5.0 | dog | no | 2 |
f | 2.0 | cat | no | 3 |
g | 4.5 | snake | no | 1 |
h | NaN | cat | yes | 1 |
i | 7.0 | dog | no | 2 |
j | 3.0 | dog | no | 1 |
22. 查看 DataFrame 的数据类型
df2.dtypes
age float64
animal object
priority object
visits int64
dtype: object
DataFrame 基本操作
23. 预览 DataFrame 的前 5 行数据
此方法对快速了解陌生数据集结构十分有用。
df2.head() # 默认为显示 5 行,可根据需要在括号中填入希望预览的行数
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
a | 2.5 | cat | yes | 1 |
b | 3.0 | cat | yes | 3 |
c | 0.5 | snake | no | 2 |
d | NaN | dog | yes | 3 |
e | 5.0 | dog | no | 2 |
24. 查看 DataFrame 的后 3 行数据
df2.tail(3)
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
h | NaN | cat | yes | 1 |
i | 7.0 | dog | no | 2 |
j | 3.0 | dog | no | 1 |
25.查看 DataFrame 的索引
df2.index
Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], dtype='object')
26. 查看 DataFrame 的列名
df2.columns
Index(['age', 'animal', 'priority', 'visits'], dtype='object')
27. 查看 DataFrame 的数值
df2.values
array([[2.5, 'cat', 'yes', 1],
[3.0, 'cat', 'yes', 3],
[0.5, 'snake', 'no', 2],
[nan, 'dog', 'yes', 3],
[5.0, 'dog', 'no', 2],
[2.0, 'cat', 'no', 3],
[4.5, 'snake', 'no', 1],
[nan, 'cat', 'yes', 1],
[7.0, 'dog', 'no', 2],
[3.0, 'dog', 'no', 1]], dtype=object)
28. 查看 DataFrame 的统计数据
df2.describe()
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | visits | |
---|---|---|
count | 8.000000 | 10.000000 |
mean | 3.437500 | 1.900000 |
std | 2.007797 | 0.875595 |
min | 0.500000 | 1.000000 |
25% | 2.375000 | 1.000000 |
50% | 3.000000 | 2.000000 |
75% | 4.625000 | 2.750000 |
max | 7.000000 | 3.000000 |
29. DataFrame 转置操作
df2.T
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
a | b | c | d | e | f | g | h | i | j | |
---|---|---|---|---|---|---|---|---|---|---|
age | 2.5 | 3 | 0.5 | NaN | 5 | 2 | 4.5 | NaN | 7 | 3 |
animal | cat | cat | snake | dog | dog | cat | snake | cat | dog | dog |
priority | yes | yes | no | yes | no | no | no | yes | no | no |
visits | 1 | 3 | 2 | 3 | 2 | 3 | 1 | 1 | 2 | 1 |
30. 对 DataFrame 进行按列排序
df2.sort_values(by='age') # 按 age 升序排列
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
c | 0.5 | snake | no | 2 |
f | 2.0 | cat | no | 3 |
a | 2.5 | cat | yes | 1 |
b | 3.0 | cat | yes | 3 |
j | 3.0 | dog | no | 1 |
g | 4.5 | snake | no | 1 |
e | 5.0 | dog | no | 2 |
i | 7.0 | dog | no | 2 |
d | NaN | dog | yes | 3 |
h | NaN | cat | yes | 1 |
31. 对 DataFrame 数据切片
df2[1:3]
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
b | 3.0 | cat | yes | 3 |
c | 0.5 | snake | no | 2 |
32. 对 DataFrame 通过标签查询(单列)
df2['age']
a 2.5
b 3.0
c 0.5
d NaN
e 5.0
f 2.0
g 4.5
h NaN
i 7.0
j 3.0
Name: age, dtype: float64
df2.age # 等价于 df2['age']
a 2.5
b 3.0
c 0.5
d NaN
e 5.0
f 2.0
g 4.5
h NaN
i 7.0
j 3.0
Name: age, dtype: float64
33. 对 DataFrame 通过标签查询(多列)
df2[['age','animal']] # 传入一个列名组成的列表
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | |
---|---|---|
a | 2.5 | cat |
b | 3.0 | cat |
c | 0.5 | snake |
d | NaN | dog |
e | 5.0 | dog |
f | 2.0 | cat |
g | 4.5 | snake |
h | NaN | cat |
i | 7.0 | dog |
j | 3.0 | dog |
34. 对 DataFrame 通过位置查询
df2.iloc[1:3] # 查询 2,3 行
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
b | 3.0 | cat | yes | 3 |
c | 0.5 | snake | no | 2 |
35. DataFrame 副本拷贝
# 生成 DataFrame 副本,方便数据集被多个不同流程使用
df3=df2.copy()
df3
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
a | 2.5 | cat | yes | 1 |
b | 3.0 | cat | yes | 3 |
c | 0.5 | snake | no | 2 |
d | NaN | dog | yes | 3 |
e | 5.0 | dog | no | 2 |
f | 2.0 | cat | no | 3 |
g | 4.5 | snake | no | 1 |
h | NaN | cat | yes | 1 |
i | 7.0 | dog | no | 2 |
j | 3.0 | dog | no | 1 |
36. 判断 DataFrame 元素是否为空
df3.isnull() # 如果为空则返回为 True
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
a | False | False | False | False |
b | False | False | False | False |
c | False | False | False | False |
d | True | False | False | False |
e | False | False | False | False |
f | False | False | False | False |
g | False | False | False | False |
h | True | False | False | False |
i | False | False | False | False |
j | False | False | False | False |
37. 添加列数据
num=pd.Series([0,1,2,3,4,5,6,7,8,9],index=df3.index)
df3['No.']=num # 添加以 'No.' 为列名的新数据列
df3
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | No. | |
---|---|---|---|---|---|
a | 2.5 | cat | yes | 1 | 0 |
b | 3.0 | cat | yes | 3 | 1 |
c | 0.5 | snake | no | 2 | 2 |
d | NaN | dog | yes | 3 | 3 |
e | 5.0 | dog | no | 2 | 4 |
f | 2.0 | cat | no | 3 | 5 |
g | 4.5 | snake | no | 1 | 6 |
h | NaN | cat | yes | 1 | 7 |
i | 7.0 | dog | no | 2 | 8 |
j | 3.0 | dog | no | 1 | 9 |
38. 根据 DataFrame 的下标值进行更改。
# 修改第 2 行与第 1 列对应的值 3.0 → 2.0
df3.iat[1,0]=2 # 索引序号从 0 开始,这里为 1, 0
df3
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | No. | |
---|---|---|---|---|---|
a | 2.5 | cat | yes | 1 | 0 |
b | 2.0 | cat | yes | 3 | 1 |
c | 0.5 | snake | no | 2 | 2 |
d | NaN | dog | yes | 3 | 3 |
e | 5.0 | dog | no | 2 | 4 |
f | 2.0 | cat | no | 3 | 5 |
g | 4.5 | snake | no | 1 | 6 |
h | NaN | cat | yes | 1 | 7 |
i | 7.0 | dog | no | 2 | 8 |
j | 3.0 | dog | no | 1 | 9 |
39. 根据 DataFrame 的标签对数据进行修改
df3.loc['f','age']=1.5
df3
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | No. | |
---|---|---|---|---|---|
a | 2.5 | cat | yes | 1 | 0 |
b | 2.0 | cat | yes | 3 | 1 |
c | 0.5 | snake | no | 2 | 2 |
d | NaN | dog | yes | 3 | 3 |
e | 5.0 | dog | no | 2 | 4 |
f | 1.5 | cat | no | 3 | 5 |
g | 4.5 | snake | no | 1 | 6 |
h | NaN | cat | yes | 1 | 7 |
i | 7.0 | dog | no | 2 | 8 |
j | 3.0 | dog | no | 1 | 9 |
40. DataFrame 求平均值操作
df3.mean()
age 3.25
visits 1.90
No. 4.50
dtype: float64
41. 对 DataFrame 中任意列做求和操作
df3['visits'].sum()
19
字符串操作
42. 将字符串转化为小写字母
string = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
print(string)
string.str.lower()
0 A
1 B
2 C
3 Aaba
4 Baca
5 NaN
6 CABA
7 dog
8 cat
dtype: object
0 a
1 b
2 c
3 aaba
4 baca
5 NaN
6 caba
7 dog
8 cat
dtype: object
43. 将字符串转化为大写字母
string.str.upper()
0 A
1 B
2 C
3 AABA
4 BACA
5 NaN
6 CABA
7 DOG
8 CAT
dtype: object
DataFrame 缺失值操作
44. 对缺失值进行填充
df4=df3.copy()
print(df4)
df4.fillna(value=3)
age animal priority visits No.
a 2.5 cat yes 1 0
b 2.0 cat yes 3 1
c 0.5 snake no 2 2
d NaN dog yes 3 3
e 5.0 dog no 2 4
f 1.5 cat no 3 5
g 4.5 snake no 1 6
h NaN cat yes 1 7
i 7.0 dog no 2 8
j 3.0 dog no 1 9
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | No. | |
---|---|---|---|---|---|
a | 2.5 | cat | yes | 1 | 0 |
b | 2.0 | cat | yes | 3 | 1 |
c | 0.5 | snake | no | 2 | 2 |
d | 3.0 | dog | yes | 3 | 3 |
e | 5.0 | dog | no | 2 | 4 |
f | 1.5 | cat | no | 3 | 5 |
g | 4.5 | snake | no | 1 | 6 |
h | 3.0 | cat | yes | 1 | 7 |
i | 7.0 | dog | no | 2 | 8 |
j | 3.0 | dog | no | 1 | 9 |
45. 删除存在缺失值的行
df5=df3.copy()
print(df5)
df5.dropna(how='any') # 任何存在 NaN 的行都将被删除
age animal priority visits No.
a 2.5 cat yes 1 0
b 2.0 cat yes 3 1
c 0.5 snake no 2 2
d NaN dog yes 3 3
e 5.0 dog no 2 4
f 1.5 cat no 3 5
g 4.5 snake no 1 6
h NaN cat yes 1 7
i 7.0 dog no 2 8
j 3.0 dog no 1 9
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | No. | |
---|---|---|---|---|---|
a | 2.5 | cat | yes | 1 | 0 |
b | 2.0 | cat | yes | 3 | 1 |
c | 0.5 | snake | no | 2 | 2 |
e | 5.0 | dog | no | 2 | 4 |
f | 1.5 | cat | no | 3 | 5 |
g | 4.5 | snake | no | 1 | 6 |
i | 7.0 | dog | no | 2 | 8 |
j | 3.0 | dog | no | 1 | 9 |
46. DataFrame 按指定列对齐
left = pd.DataFrame({'key': ['foo1', 'foo2'], 'one': [1, 2]})
right = pd.DataFrame({'key': ['foo2', 'foo3'], 'two': [4, 5]})
print(left)
print(right)
# 按照 key 列对齐连接,只存在 foo2 相同,所以最后变成一行
pd.merge(left, right, on='key')
key one
0 foo1 1
1 foo2 2
key two
0 foo2 4
1 foo3 5
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
key | one | two | |
---|---|---|---|
0 | foo2 | 2 | 4 |
DataFrame 文件操作
47. CSV 文件写入
df3.to_csv('animal.csv')
print("写入成功.")
写入成功.
48. CSV 文件读取
df_animal=pd.read_csv('animal.csv')
df_animal
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Unnamed: 0 | age | animal | priority | visits | No. | |
---|---|---|---|---|---|---|
0 | a | 2.5 | cat | yes | 1 | 0 |
1 | b | 2.0 | cat | yes | 3 | 1 |
2 | c | 0.5 | snake | no | 2 | 2 |
3 | d | NaN | dog | yes | 3 | 3 |
4 | e | 5.0 | dog | no | 2 | 4 |
5 | f | 1.5 | cat | no | 3 | 5 |
6 | g | 4.5 | snake | no | 1 | 6 |
7 | h | NaN | cat | yes | 1 | 7 |
8 | i | 7.0 | dog | no | 2 | 8 |
9 | j | 3.0 | dog | no | 1 | 9 |
49. Excel 写入操作
df3.to_excel('animal.xlsx', sheet_name='Sheet1')
print("写入成功.")
写入成功.
50. Excel 读取操作
pd.read_excel('animal.xlsx', 'Sheet1', index_col=None, na_values=['NA'])
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | No. | |
---|---|---|---|---|---|
a | 2.5 | cat | yes | 1 | 0 |
b | 2.0 | cat | yes | 3 | 1 |
c | 0.5 | snake | no | 2 | 2 |
d | NaN | dog | yes | 3 | 3 |
e | 5.0 | dog | no | 2 | 4 |
f | 1.5 | cat | no | 3 | 5 |
g | 4.5 | snake | no | 1 | 6 |
h | NaN | cat | yes | 1 | 7 |
i | 7.0 | dog | no | 2 | 8 |
j | 3.0 | dog | no | 1 | 9 |
2. 进阶部分
时间序列索引
51. 建立一个以 2018 年每一天为索引,值为随机数的 Series
dti = pd.date_range(start='2018-01-01', end='2018-12-31', freq='D')
s = pd.Series(np.random.rand(len(dti)), index=dti)
s
2018-01-01 0.061229
2018-01-02 0.349188
2018-01-03 0.010522
2018-01-04 0.635935
2018-01-05 0.170949
2018-01-06 0.681168
2018-01-07 0.884453
2018-01-08 0.297900
2018-01-09 0.655529
2018-01-10 0.592723
2018-01-11 0.916066
2018-01-12 0.752309
2018-01-13 0.922615
2018-01-14 0.445157
2018-01-15 0.820222
2018-01-16 0.240932
2018-01-17 0.618097
2018-01-18 0.101548
2018-01-19 0.095011
2018-01-20 0.217877
2018-01-21 0.401338
2018-01-22 0.009544
2018-01-23 0.948713
2018-01-24 0.233104
2018-01-25 0.356758
2018-01-26 0.979582
2018-01-27 0.287487
2018-01-28 0.150039
2018-01-29 0.148023
2018-01-30 0.752855
...
2018-12-02 0.888667
2018-12-03 0.447761
2018-12-04 0.021689
2018-12-05 0.465762
2018-12-06 0.070157
2018-12-07 0.140246
2018-12-08 0.566471
2018-12-09 0.835420
2018-12-10 0.222262
2018-12-11 0.780987
2018-12-12 0.322011
2018-12-13 0.628845
2018-12-14 0.789033
2018-12-15 0.448480
2018-12-16 0.694076
2018-12-17 0.110494
2018-12-18 0.709268
2018-12-19 0.215171
2018-12-20 0.346239
2018-12-21 0.921734
2018-12-22 0.483171
2018-12-23 0.932054
2018-12-24 0.506611
2018-12-25 0.743286
2018-12-26 0.082379
2018-12-27 0.018389
2018-12-28 0.068085
2018-12-29 0.832097
2018-12-30 0.431205
2018-12-31 0.374142
Freq: D, Length: 365, dtype: float64
52. 统计s
中每一个周三对应值的和
# 周一从 0 开始
s[s.index.weekday == 2].sum()
26.32973591103629
53. 统计s
中每个月值的平均值
s.resample('M').mean()
2018-01-31 0.473514
2018-02-28 0.484146
2018-03-31 0.418412
2018-04-30 0.516295
2018-05-31 0.361061
2018-06-30 0.528159
2018-07-31 0.504941
2018-08-31 0.518669
2018-09-30 0.535072
2018-10-31 0.568562
2018-11-30 0.628084
2018-12-31 0.459521
Freq: M, dtype: float64
54. 将 Series 中的时间进行转换(秒转分钟)
s = pd.date_range('today', periods=100, freq='S')
ts = pd.Series(np.random.randint(0, 500, len(s)), index=s)
ts.resample('Min').sum()
2018-04-17 01:12:00 4940
2018-04-17 01:13:00 15498
2018-04-17 01:14:00 5196
Freq: T, dtype: int64
55. UTC 世界时间标准
s = pd.date_range('today', periods=1, freq='D') # 获取当前时间
ts = pd.Series(np.random.randn(len(s)), s) # 随机数值
ts_utc = ts.tz_localize('UTC') # 转换为 UTC 时间
ts_utc
2018-04-17 01:12:39.582169+00:00 1.175686
Freq: D, dtype: float64
56. 转换为上海所在时区
ts_utc.tz_convert('Asia/Shanghai')
2018-04-17 09:12:39.582169+08:00 1.175686
Freq: D, dtype: float64
看一看你当前的时间,是不是一致?
57.不同时间表示方式的转换
rng = pd.date_range('1/1/2018', periods=5, freq='M')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
print (ts)
ps = ts.to_period()
print(ps)
ps.to_timestamp()
2018-01-31 1.462008
2018-02-28 0.529459
2018-03-31 1.403390
2018-04-30 0.787675
2018-05-31 0.755009
Freq: M, dtype: float64
2018-01 1.462008
2018-02 0.529459
2018-03 1.403390
2018-04 0.787675
2018-05 0.755009
Freq: M, dtype: float64
2018-01-01 1.462008
2018-02-01 0.529459
2018-03-01 1.403390
2018-04-01 0.787675
2018-05-01 0.755009
Freq: MS, dtype: float64
Series 多重索引 [选学]
58. 创建多重索引 Series
构建一个 letters = ['A', 'B', 'C']
和 numbers = list(range(10))
为索引,值为随机数的多重索引 Series。
letters = ['A', 'B', 'C']
numbers = list(range(10))
mi = pd.MultiIndex.from_product([letters, numbers]) # 设置多重索引
s = pd.Series(np.random.rand(30), index=mi) # 随机数
s
A 0 0.153254
1 0.603413
2 0.807854
3 0.965357
4 0.647967
5 0.863231
6 0.490679
7 0.566480
8 0.254349
9 0.043830
B 0 0.707389
1 0.517383
2 0.210780
3 0.567798
4 0.362029
5 0.493134
6 0.822650
7 0.333771
8 0.737994
9 0.126518
C 0 0.921987
1 0.933315
2 0.689457
3 0.974962
4 0.136616
5 0.625680
6 0.127213
7 0.242088
8 0.873949
9 0.399730
dtype: float64
59. 多重索引 Series 查询
# 查询索引为 1,3,6 的值
s.loc[:, [1, 3, 6]]
A 1 0.603413
3 0.965357
6 0.490679
B 1 0.517383
3 0.567798
6 0.822650
C 1 0.933315
3 0.974962
6 0.127213
dtype: float64
60. 多重索引 Series 切片
s.loc[pd.IndexSlice[:'B', 5:]]
A 5 0.863231
6 0.490679
7 0.566480
8 0.254349
9 0.043830
B 5 0.493134
6 0.822650
7 0.333771
8 0.737994
9 0.126518
dtype: float64
DataFrame 多重索引 [选学]
61. 根据多重索引创建 DataFrame
创建一个以 letters = ['A', 'B']
和 numbers = list(range(6))
为索引,值为随机数据的多重索引 DataFrame。
frame=pd.DataFrame(np.arange(12).reshape(6,2),
index=[list('AAABBB'),list('123123')],
columns=['hello','shiyanlou'])
frame
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
hello | shiyanlou | ||
---|---|---|---|
A | 1 | 0 | 1 |
2 | 2 | 3 | |
3 | 4 | 5 | |
B | 1 | 6 | 7 |
2 | 8 | 9 | |
3 | 10 | 11 |
62. 多重索引设置列名称
frame.index.names=['first','second']
frame
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
hello | shiyanlou | ||
---|---|---|---|
first | second | ||
A | 1 | 0 | 1 |
2 | 2 | 3 | |
3 | 4 | 5 | |
B | 1 | 6 | 7 |
2 | 8 | 9 | |
3 | 10 | 11 |
63. DataFrame 多重索引分组求和
frame.groupby('first').sum()
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
hello | shiyanlou | |
---|---|---|
first | ||
A | 6 | 9 |
B | 24 | 27 |
64. DataFrame 行列名称转换
print(frame)
frame.stack()
hello shiyanlou
first second
A 1 0 1
2 2 3
3 4 5
B 1 6 7
2 8 9
3 10 11
first second
A 1 hello 0
shiyanlou 1
2 hello 2
shiyanlou 3
3 hello 4
shiyanlou 5
B 1 hello 6
shiyanlou 7
2 hello 8
shiyanlou 9
3 hello 10
shiyanlou 11
dtype: int64
65. DataFrame 索引转换
print(frame)
frame.unstack()
hello shiyanlou
first second
A 1 0 1
2 2 3
3 4 5
B 1 6 7
2 8 9
3 10 11
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead tr th {
text-align: left;
}
.dataframe thead tr:last-of-type th {
text-align: right;
}
hello | shiyanlou | |||||
---|---|---|---|---|---|---|
second | 1 | 2 | 3 | 1 | 2 | 3 |
first | ||||||
A | 0 | 2 | 4 | 1 | 3 | 5 |
B | 6 | 8 | 10 | 7 | 9 | 11 |
66. DataFrame 条件查找
# 示例数据
data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'],
'age': [2.5, 3, 0.5, np.nan, 5, 2, 4.5, np.nan, 7, 3],
'visits': [1, 3, 2, 3, 2, 3, 1, 1, 2, 1],
'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']}
labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
df = pd.DataFrame(data, index=labels)
查找 age
大于 3
的全部信息
df[df['age'] > 3]
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
e | 5.0 | dog | no | 2 |
g | 4.5 | snake | no | 1 |
i | 7.0 | dog | no | 2 |
67. 根据行列索引切片
df.iloc[2:4, 1:3]
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
animal | priority | |
---|---|---|
c | snake | no |
d | dog | yes |
68. DataFrame 多重条件查询
查找 age<3
且为 cat
的全部数据。
df = pd.DataFrame(data, index=labels)
df[(df['animal'] == 'cat') & (df['age'] < 3)]
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
a | 2.5 | cat | yes | 1 |
f | 2.0 | cat | no | 3 |
69. DataFrame 按关键字查询
df3[df3['animal'].isin(['cat', 'dog'])]
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | No. | |
---|---|---|---|---|---|
a | 2.5 | cat | yes | 1 | 0 |
b | 2.0 | cat | yes | 3 | 1 |
d | NaN | dog | yes | 3 | 3 |
e | 5.0 | dog | no | 2 | 4 |
f | 1.5 | cat | no | 3 | 5 |
h | NaN | cat | yes | 1 | 7 |
i | 7.0 | dog | no | 2 | 8 |
j | 3.0 | dog | no | 1 | 9 |
70. DataFrame 按标签及列名查询。
df.loc[df2.index[[3, 4, 8]], ['animal', 'age']]
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
animal | age | |
---|---|---|
d | dog | NaN |
e | dog | 5.0 |
i | dog | 7.0 |
71. DataFrame 多条件排序
按照 age
降序,visits
升序排列
df.sort_values(by=['age', 'visits'], ascending=[False, True])
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | animal | priority | visits | |
---|---|---|---|---|
i | 7.0 | dog | no | 2 |
e | 5.0 | dog | no | 2 |
g | 4.5 | snake | no | 1 |
j | 3.0 | dog | no | 1 |
b | 3.0 | cat | yes | 3 |
a | 2.5 | cat | yes | 1 |
f | 2.0 | cat | no | 3 |
c | 0.5 | snake | no | 2 |
h | NaN | cat | yes | 1 |
d | NaN | dog | yes | 3 |
72.DataFrame 多值替换
将 priority
列的 yes
值替换为 True
,no
值替换为 False
。
df['priority'].map({'yes': True, 'no': False})
a True
b True
c False
d True
e False
f False
g False
h True
i False
j False
Name: priority, dtype: bool
73. DataFrame 分组求和
df4.groupby('animal').sum()
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
age | visits | No. | |
---|---|---|---|
animal | |||
cat | 6.0 | 8 | 13 |
dog | 15.0 | 8 | 24 |
snake | 5.0 | 3 | 8 |
74. 使用列表拼接多个 DataFrame
temp_df1 = pd.DataFrame(np.random.randn(5, 4)) # 生成由随机数组成的 DataFrame 1
temp_df2 = pd.DataFrame(np.random.randn(5, 4)) # 生成由随机数组成的 DataFrame 2
temp_df3 = pd.DataFrame(np.random.randn(5, 4)) # 生成由随机数组成的 DataFrame 3
print(temp_df1)
print(temp_df2)
print(temp_df3)
pieces = [temp_df1,temp_df2,temp_df3]
pd.concat(pieces)
0 1 2 3
0 -1.621771 0.579687 0.200543 2.006745
1 -1.278790 1.079607 0.562677 -1.652881
2 -0.239869 1.472622 -1.467726 1.578908
3 -0.477516 -0.521446 -1.385550 -1.636021
4 1.657595 0.198652 1.767118 0.456760
0 1 2 3
0 1.034153 0.718432 1.204188 0.960380
1 -1.056602 0.070941 0.791236 -1.346131
2 0.773610 -0.646171 -0.271356 -0.912040
3 0.518741 0.585176 -2.642275 -0.353737
4 -1.934025 1.083801 1.202488 0.086695
0 1 2 3
0 -1.091708 -1.825958 1.425516 -1.147759
1 0.165842 0.342082 0.047206 0.206161
2 1.568157 -1.225719 -0.029439 -0.348011
3 -0.485238 -1.107424 0.580619 0.156415
4 1.049565 1.481332 -1.449734 0.525902
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | -1.621771 | 0.579687 | 0.200543 | 2.006745 |
1 | -1.278790 | 1.079607 | 0.562677 | -1.652881 |
2 | -0.239869 | 1.472622 | -1.467726 | 1.578908 |
3 | -0.477516 | -0.521446 | -1.385550 | -1.636021 |
4 | 1.657595 | 0.198652 | 1.767118 | 0.456760 |
0 | 1.034153 | 0.718432 | 1.204188 | 0.960380 |
1 | -1.056602 | 0.070941 | 0.791236 | -1.346131 |
2 | 0.773610 | -0.646171 | -0.271356 | -0.912040 |
3 | 0.518741 | 0.585176 | -2.642275 | -0.353737 |
4 | -1.934025 | 1.083801 | 1.202488 | 0.086695 |
0 | -1.091708 | -1.825958 | 1.425516 | -1.147759 |
1 | 0.165842 | 0.342082 | 0.047206 | 0.206161 |
2 | 1.568157 | -1.225719 | -0.029439 | -0.348011 |
3 | -0.485238 | -1.107424 | 0.580619 | 0.156415 |
4 | 1.049565 | 1.481332 | -1.449734 | 0.525902 |
75. 找出 DataFrame 表中和最小的列
df = pd.DataFrame(np.random.random(size=(5, 10)), columns=list('abcdefghij'))
print(df)
df.sum().idxmin() # idxmax(), idxmin() 为 Series 函数返回最大最小值的索引值
a b c d e f g \
0 0.459543 0.813660 0.577479 0.546959 0.445853 0.910802 0.458357
1 0.705980 0.983543 0.362305 0.101614 0.441129 0.303622 0.153069
2 0.062533 0.972123 0.974234 0.453502 0.587044 0.793816 0.708400
3 0.107638 0.820834 0.788659 0.553940 0.871344 0.505403 0.603718
4 0.354637 0.082698 0.428055 0.767189 0.124980 0.330075 0.949386
h i j
0 0.789885 0.108764 0.910048
1 0.644578 0.889738 0.419051
2 0.031168 0.422028 0.428225
3 0.489400 0.636219 0.191308
4 0.996606 0.006590 0.896258
‘a’
76. DataFrame 中每个元素减去每一行的平均值
df = pd.DataFrame(np.random.random(size=(5, 3)))
print(df)
df.sub(df.mean(axis=1), axis=0)
0 1 2
0 0.004074 0.279225 0.200856
1 0.220552 0.560038 0.012375
2 0.948336 0.975982 0.559181
3 0.935195 0.034609 0.335237
4 0.334189 0.198465 0.886327
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
0 | 1 | 2 | |
---|---|---|---|
0 | -0.157311 | 0.117840 | 0.039471 |
1 | -0.043770 | 0.295716 | -0.251947 |
2 | 0.120503 | 0.148149 | -0.268652 |
3 | 0.500181 | -0.400405 | -0.099776 |
4 | -0.138805 | -0.274528 | 0.413333 |
77. DataFrame 分组,并得到每一组中最大三个数之和
df = pd.DataFrame({'A': list('aaabbcaabcccbbc'),
'B': [12,345,3,1,45,14,4,52,54,23,235,21,57,3,87]})
print(df)
df.groupby('A')['B'].nlargest(3).sum(level=0)
A B
0 a 12
1 a 345
2 a 3
3 b 1
4 b 45
5 c 14
6 a 4
7 a 52
8 b 54
9 c 23
10 c 235
11 c 21
12 b 57
13 b 3
14 c 87
A
a 409
b 156
c 345
Name: B, dtype: int64
透视表 [选学]
当分析庞大的数据时,为了更好的发掘数据特征之间的关系,且不破坏原数据,就可以利用透视表 pivot_table
进行操作。
78. 透视表的创建
新建表将 A, B, C
列作为索引进行聚合。
df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,
'B' : ['A', 'B', 'C'] * 4,
'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
'D' : np.random.randn(12),
'E' : np.random.randn(12)})
print(df)
pd.pivot_table(df, index=['A', 'B'])
A B C D E
0 one A foo -0.514210 -1.131103
1 one B foo -0.117740 -0.947978
2 two C foo 0.289447 -1.379876
3 three A bar -1.487939 2.539993
4 one B bar 1.677884 -0.035755
5 one C bar 1.314473 -1.068254
6 two A foo 0.720338 0.179532
7 three B foo -0.142951 0.274006
8 one C foo -1.792092 -0.983871
9 one A bar -0.601611 0.533527
10 two B bar 0.654210 -0.188782
11 three C bar 1.480571 -0.917102
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
D | E | ||
---|---|---|---|
A | B | ||
one | A | -0.557911 | -0.298788 |
B | 0.780072 | -0.491867 | |
C | -0.238809 | -1.026063 | |
three | A | -1.487939 | 2.539993 |
B | -0.142951 | 0.274006 | |
C | 1.480571 | -0.917102 | |
two | A | 0.720338 | 0.179532 |
B | 0.654210 | -0.188782 | |
C | 0.289447 | -1.379876 |
79. 透视表按指定行进行聚合
将该 DataFrame 的 D
列聚合,按照 A,B
列为索引进行聚合,聚合的方式为默认求均值。
pd.pivot_table(df,values=['D'],index=['A', 'B'])
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
D | ||
---|---|---|
A | B | |
one | A | -0.557911 |
B | 0.780072 | |
C | -0.238809 | |
three | A | -1.487939 |
B | -0.142951 | |
C | 1.480571 | |
two | A | 0.720338 |
B | 0.654210 | |
C | 0.289447 |
80. 透视表聚合方式定义
上一题中 D
列聚合时,采用默认求均值的方法,若想使用更多的方式可以在 aggfunc
中实现。
pd.pivot_table(df,values=['D'],index=['A', 'B'],aggfunc=[np.sum, len])
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead tr th {
text-align: left;
}
.dataframe thead tr:last-of-type th {
text-align: right;
}
sum | len | ||
---|---|---|---|
D | D | ||
A | B | ||
one | A | -1.115822 | 2.0 |
B | 1.560144 | 2.0 | |
C | -0.477619 | 2.0 | |
three | A | -1.487939 | 1.0 |
B | -0.142951 | 1.0 | |
C | 1.480571 | 1.0 | |
two | A | 0.720338 | 1.0 |
B | 0.654210 | 1.0 | |
C | 0.289447 | 1.0 |
81. 透视表利用额外列进行辅助分割
D
列按照 A,B
列进行聚合时,若关心 C
列对 D
列的影响,可以加入 columns
值进行分析。
pd.pivot_table(df,values=['D'],index=['A', 'B'],columns=['C'],aggfunc=np.sum)
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead tr th {
text-align: left;
}
.dataframe thead tr:last-of-type th {
text-align: right;
}
D | |||
---|---|---|---|
C | bar | foo | |
A | B | ||
one | A | -0.601611 | -0.514210 |
B | 1.677884 | -0.117740 | |
C | 1.314473 | -1.792092 | |
three | A | -1.487939 | NaN |
B | NaN | -0.142951 | |
C | 1.480571 | NaN | |
two | A | NaN | 0.720338 |
B | 0.654210 | NaN | |
C | NaN | 0.289447 |
82. 透视表的缺省值处理
在透视表中由于不同的聚合方式,相应缺少的组合将为缺省值,可以加入 fill_value
对缺省值处理。
pd.pivot_table(df,values=['D'],index=['A', 'B'],columns=['C'],aggfunc=np.sum,fill_value=0)
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead tr th {
text-align: left;
}
.dataframe thead tr:last-of-type th {
text-align: right;
}
D | |||
---|---|---|---|
C | bar | foo | |
A | B | ||
one | A | -0.601611 | -0.514210 |
B | 1.677884 | -0.117740 | |
C | 1.314473 | -1.792092 | |
three | A | -1.487939 | 0.000000 |
B | 0.000000 | -0.142951 | |
C | 1.480571 | 0.000000 | |
two | A | 0.000000 | 0.720338 |
B | 0.654210 | 0.000000 | |
C | 0.000000 | 0.289447 |
绝对类型 [选学]
在数据的形式上主要包括数量型和性质型,数量型表示着数据可数范围可变,而性质型表示范围已经确定不可改变,绝对型数据就是性质型数据的一种。
83. 绝对型数据定义
df = pd.DataFrame({"id":[1,2,3,4,5,6], "raw_grade":['a', 'b', 'b', 'a', 'a', 'e']})
df["grade"] = df["raw_grade"].astype("category")
df
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
id | raw_grade | grade | |
---|---|---|---|
0 | 1 | a | a |
1 | 2 | b | b |
2 | 3 | b | b |
3 | 4 | a | a |
4 | 5 | a | a |
5 | 6 | e | e |
84. 对绝对型数据重命名
df["grade"].cat.categories = ["very good", "good", "very bad"]
df
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
id | raw_grade | grade | |
---|---|---|---|
0 | 1 | a | very good |
1 | 2 | b | good |
2 | 3 | b | good |
3 | 4 | a | very good |
4 | 5 | a | very good |
5 | 6 | e | very bad |
85. 重新排列绝对型数据并补充相应的缺省值
df["grade"] = df["grade"].cat.set_categories(["very bad", "bad", "medium", "good", "very good"])
df
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
id | raw_grade | grade | |
---|---|---|---|
0 | 1 | a | very good |
1 | 2 | b | good |
2 | 3 | b | good |
3 | 4 | a | very good |
4 | 5 | a | very good |
5 | 6 | e | very bad |
86. 对绝对型数据进行排序
df.sort_values(by="grade")
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
id | raw_grade | grade | |
---|---|---|---|
5 | 6 | e | very bad |
1 | 2 | b | good |
2 | 3 | b | good |
0 | 1 | a | very good |
3 | 4 | a | very good |
4 | 5 | a | very good |
87. 对绝对型数据进行分组
df.groupby("grade").size()
grade
very bad 1
bad 0
medium 0
good 2
very good 3
dtype: int64
数据清洗 [选学]
常常我们得到的数据是不符合我们最终处理的数据要求,包括许多缺省值以及坏的数据,需要我们对数据进行清洗。
88. 缺失值拟合
在FilghtNumber
中有数值缺失,其中数值为按 10 增长,补充相应的缺省值使得数据完整,并让数据为 int
类型。
df = pd.DataFrame({'From_To': ['LoNDon_paris', 'MAdrid_miLAN', 'londON_StockhOlm',
'Budapest_PaRis', 'Brussels_londOn'],
'FlightNumber': [10045, np.nan, 10065, np.nan, 10085],
'RecentDelays': [[23, 47], [], [24, 43, 87], [13], [67, 32]],
'Airline': ['KLM(!)', '<Air France> (12)', '(British Airways. )',
'12. Air France', '"Swiss Air"']})
df['FlightNumber'] = df['FlightNumber'].interpolate().astype(int)
df
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Airline | FlightNumber | From_To | RecentDelays | |
---|---|---|---|---|
0 | KLM(!) | 10045 | LoNDon_paris | [23, 47] |
1 | <Air France> (12) | 10055 | MAdrid_miLAN | [] |
2 | (British Airways. ) | 10065 | londON_StockhOlm | [24, 43, 87] |
3 | 12. Air France | 10075 | Budapest_PaRis | [13] |
4 | “Swiss Air” | 10085 | Brussels_londOn | [67, 32] |
89. 数据列拆分
其中From_to
应该为两独立的两列From
和To
,将From_to
依照拆分为独立两列建立为一个新表。
temp = df.From_To.str.split('', expand=True)
temp.columns = ['From', 'To']
temp
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
From | To | |
---|---|---|
0 | LoNDon | paris |
1 | MAdrid | miLAN |
2 | londON | StockhOlm |
3 | Budapest | PaRis |
4 | Brussels | londOn |
90. 字符标准化
其中注意到地点的名字都不规范(如:londON
应该为London
)需要对数据进行标准化处理。
temp['From'] = temp['From'].str.capitalize()
temp['To'] = temp['To'].str.capitalize()
91. 删除坏数据加入整理好的数据
将最开始的From_to
列删除,加入整理好的From
和to
列。
df = df.drop('From_To', axis=1)
df = df.join(temp)
print(df)
Airline FlightNumber RecentDelays From To
0 KLM(!) 10045 [23, 47] London Paris
1 <Air France> (12) 10055 [] Madrid Milan
2 (British Airways. ) 10065 [24, 43, 87] London Stockholm
3 12. Air France 10075 [13] Budapest Paris
4 "Swiss Air" 10085 [67, 32] Brussels London
92. 去除多余字符
如同 airline
列中许多数据有许多其他字符,会对后期的数据分析有较大影响,需要对这类数据进行修正。
df['Airline'] = df['Airline'].str.extract('([a-zA-Z\s]+)', expand=False).str.strip()
df
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Airline | FlightNumber | RecentDelays | From | To | |
---|---|---|---|---|---|
0 | KLM | 10045 | [23, 47] | London | Paris |
1 | Air France | 10055 | [] | Madrid | Milan |
2 | British Airways | 10065 | [24, 43, 87] | London | Stockholm |
3 | Air France | 10075 | [13] | Budapest | Paris |
4 | Swiss Air | 10085 | [67, 32] | Brussels | London |
93. 格式规范
在 RecentDelays
中记录的方式为列表类型,由于其长度不一,这会为后期数据分析造成很大麻烦。这里将 RecentDelays
的列表拆开,取出列表中的相同位置元素作为一列,若为空值即用 NaN
代替。
delays = df['RecentDelays'].apply(pd.Series)
delays.columns = ['delay_{}'.format(n) for n in range(1, len(delays.columns)+1)]
df = df.drop('RecentDelays', axis=1).join(delays)
df
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
Airline | FlightNumber | From | To | delay_1 | delay_2 | delay_3 | |
---|---|---|---|---|---|---|---|
0 | KLM | 10045 | London | Paris | 23.0 | 47.0 | NaN |
1 | Air France | 10055 | Madrid | Milan | NaN | NaN | NaN |
2 | British Airways | 10065 | London | Stockholm | 24.0 | 43.0 | 87.0 |
3 | Air France | 10075 | Budapest | Paris | 13.0 | NaN | NaN |
4 | Swiss Air | 10085 | Brussels | London | 67.0 | 32.0 | NaN |
数据预处理 [选学]
94. 信息区间划分
班级一部分同学的数学成绩表,如下图所示
df=pd.DataFrame({'name':['Alice','Bob','Candy','Dany','Ella','Frank','Grace','Jenny'],'grades':[58,83,79,65,93,45,61,88]})
但我们更加关心的是该同学是否及格,将该数学成绩按照是否>60
来进行划分。
df=pd.DataFrame({'name':['Alice','Bob','Candy','Dany','Ella','Frank','Grace','Jenny'],'grades':[58,83,79,65,93,45,61,88]})
def choice(x):
if x>60:
return 1
else:
return 0
df.grades=pd.Series(map(lambda x:choice(x),df.grades))
df
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
grades | name | |
---|---|---|
0 | 0 | Alice |
1 | 1 | Bob |
2 | 1 | Candy |
3 | 1 | Dany |
4 | 1 | Ella |
5 | 0 | Frank |
6 | 1 | Grace |
7 | 1 | Jenny |
95. 数据去重
一个列为A
的 DataFrame 数据,如下图所示
df = pd.DataFrame({'A': [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7]})
如何将 A 列中重复的数据清除。
df = pd.DataFrame({'A': [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7]})
df.loc[df['A'].shift() != df['A']]
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
A | |
---|---|
0 | 1 |
1 | 2 |
3 | 3 |
4 | 4 |
5 | 5 |
8 | 6 |
9 | 7 |
96. 数据归一化
有时候,DataFrame 中不同列之间的数据差距太大,需要对其进行归一化处理。
其中,Max-Min 归一化是简单而常见的一种方式,公式如下:
Y=X−XminXmax−XminY=\frac{X-X_{min}}{X_{max}-X_{min}}Y=Xmax−XminX−Xmin
def normalization(df):
numerator=df.sub(df.min())
denominator=(df.max()).sub(df.min())
Y=numerator.div(denominator)
return Y
df = pd.DataFrame(np.random.random(size=(5, 3)))
print(df)
normalization(df)
0 1 2
0 0.371083 0.025493 0.284655
1 0.762037 0.688582 0.143784
2 0.789632 0.495761 0.870860
3 0.551070 0.323666 0.932261
4 0.847153 0.896437 0.116094
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
0 | 1 | 2 | |
---|---|---|---|
0 | 0.000000 | 0.000000 | 0.206528 |
1 | 0.821212 | 0.761345 | 0.033926 |
2 | 0.879175 | 0.539952 | 0.924769 |
3 | 0.378068 | 0.342356 | 1.000000 |
4 | 1.000000 | 1.000000 | 0.000000 |
Pandas 绘图操作
为了更好的了解数据包含的信息,最直观的方法就是将其绘制成图。
97. Series 可视化
%matplotlib inline
ts = pd.Series(np.random.randn(100), index=pd.date_range('today', periods=100))
ts = ts.cumsum()
ts.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7f47dfae76d8>
98. DataFrame 折线图
df = pd.DataFrame(np.random.randn(100, 4), index=ts.index,
columns=['A', 'B', 'C', 'D'])
df = df.cumsum()
df.plot()
99. DataFrame 散点图
df = pd.DataFrame({"xs":[1,5,2,8,1], "ys":[4,2,1,9,6]})
df = df.cumsum()
df.plot.scatter("xs","ys",color='red',marker="*")
100. DataFrame 柱形图
df = pd.DataFrame({"revenue":[57,68,63,71,72,90,80,62,59,51,47,52],
"advertising":[2.1,1.9,2.7,3.0,3.6,3.2,2.7,2.4,1.8,1.6,1.3,1.9],
"month":range(12)
})
ax = df.plot.bar("month", "revenue", color = "yellow")
df.plot("month", "advertising", secondary_y = True, ax = ax)
3. 实验总结
如果你亲自动手做完了上面的 100 道练习题,相信你已经对 Pandas 模块的熟练程度又提升了不少。我们推荐你定期回顾这些题目,相信你一定会熟能生巧。本次实验涉及的知识点主要有:
- 创建Series
- Series基本操作
- 创建DataFrame
- DataFrame基本操作
- DataFrame文件操作
- Series,DataFrame和多索引
- 透视表
- 数据清洗
- 数据预处理
- 可视化