在普通高中教科书技术必修一中,第四章数据分析的Pandas模块一直是一个难点。不容易讲透,学生不容易搞懂,教程的编写也没有给出适当的举例。很多情况下需要学生自己上机打代码,但是种种原因把限制在课本中。

今天我们就对照着教程,把Pandas模块每一个函数搞懂。

本文会进行适当举例,举例如有雷同,纯属巧合


导入Pandas模块

如果你已经成功安装了Pandas模块,那么你可以在IDE中导入Pandas模块进行数据处理。

1
import pandas   #导入pandas模块

如果这样import,那么接下来使用pandas的子模块,必须在头部加上pandas,如:

1
s1=pandas.Series([1,2,3])   #创捷一个Series对象,我们后面讲它

当然你也可以只导入Pandas的一个子模块,当然用这个子模块的时候就可以直接使用了。

1
2
3
4
5
6
7
8
9
from pandas import Series
s1=Series([1,2,3])
print(s1)

输出结果:
0 1
1 2
2 3
dtype: int64

如果需要同时使用Pandas的两个子模块模块,又觉得每次都要打Pandas这个头很烦,那么可以这样导入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd  #把pandas模块导入为pd,当然名字可以任意取
s1=pd.Series([1,2,3])
df1=pd.DataFrame({"姓名":["高明","地心"],"语文":[113,125],"数学":[98,145]},columns=["姓名","语文","数学"])
#这是DataFrame模块,我们后面慢慢讲它
print(s1)
print(df1)

输出结果:
0 1
1 2
2 3
dtype: int64
姓名 语文 数学
0 高明 113 98
1 地心 125 145

好了,现在你已经掌握怎么导入Pandas模块了!


Series子模块

课本中对Series模块的讲解比较透彻,我这里就简单的抄点课本嘿嘿~

Series是一种一维的数据结构,包含一个数组的数据和一个与数据关联的索引( index ), 索引值默认是从0起递增的整数。列表、字典等可以用来创建Series数据结构,与列表不同的是,Series 的索引可以指定,类型可以为字符串型。

看完课本的介绍,那么我们来实操一下,我们把同学们的信息用Series存储起来。

1
2
3
4
5
6
7
8
9
from pandas import Series
s1=Series(["高明","章鱼","地心"])
print(s1)

输出结果:
0 高明
1 章鱼
2 地心
dtype: object

那么我们来通过索引访问一下单个数据,我们需要找到第二个(索引为1)同学的名字。

1
2
3
4
print(s1[1])

输出结果:
章鱼

索引1和”章鱼”对应,输出了”章鱼”,没有问题。那么我们继续。
现在我们来更改一下Series里面的同学,第一个同学改成二哥

1
2
3
4
5
6
7
8
s1[0]="二哥"
print(s1)

输出结果:
0 二哥
1 章鱼
2 地心
dtype: object

更改Series里的数据是不是和更新列表元素十分相似?

根据课本里的这句话:

列表不同的是,Series 的索引可以指定,类型可以为字符串型。

那么我们也来更改一下索引,用名字来做索引,用性别来做值。

1
2
3
4
5
6
7
8
s2=Series(["female","male","male"],index=["高明","章鱼","地心"])
print(s2)

输出结果:
高明 female
章鱼 male
地心 male
dtype: object

可以看到索引变成了字符串,应用的时候索引也要用字符串,如下:

1
2
3
4
print(s2["地心"])

输出结果:
male

这里要提醒一下,如果索引个数和数据个数不匹配,运行的时候会报错!!!

这里有个很有意思的现象,就是索引不一定要独一无二,也就是说,索引是可以重复的。我们再举个例子,把性别作为索引,名字作为值:

1
2
3
4
5
6
7
8
9
10
11
12
s3=Series(["高明","章鱼","地心"],index=["female","male","male"])
print(s3)
print(s3[male])

输出结果:
female 高明
male 章鱼
male 地心
dtype: object
male 章鱼
male 地心
dtype: object

Python不但不会报错,还会把所有符合索引的内容都输出来。

我现在再抄一下课本嘿嘿,

属性 说明
index Series的下标索引,其值默认是从0起递增的整数
values 存放Series值的一个数组

其中还有查看index、values属性值的方法:

1
2
3
4
5
6
7
for i in s1.index:
print(i)

输出结果:
0
1
2
1
2
3
4
5
6
7
for i in s2.values:
print(i)

输出结果:
female
male
male
1
2
3
4
5
6
7
for i in s3:   #这里s3默认就是指代values
print(i)

输出结果:
高明
章鱼
地心

好啦,Series的讲解就到这里,是不是很轻松哇?


DataFrame子模块

DataFrame是Pandas模块的难点,函数比较多。

DataFrame是一种二维的数据结构,由1个索引列(index)和若干个数据列组成,每个数据列可以是不同的类型。DataFrame可以看作是共享同一个index的Series的集合。创建DataFrame对象的方法很多,通常用一个相等 长度的列表或字典来创建。

期中考结束了,学校发了成绩单下来,同学们十分兴奋,老师用DataFrame给他们分析成绩。

构建DataFrame对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pandas import DataFrame
df1=DataFrame({
"姓名":["高明","章鱼","地心","琐碎","石宝","二哥","如意"],
"语文":[93,109,103,125,118,113,98],
"数学":[98,145,143,134,122,103,67],
"英语":[96,105,134,119,105,135,90],
"物理":[43,58,95,68,79,67,45],
"化学":[74,41,64,52,74,52,58],
"生物":[71,78,93,78,77,60,64],
"历史":[66,52,41,52,57,50,59],
"地理":[57,63,69,84,51,51,62],
"政治":[44,41,42,65,48,48,49],
"技术":[85,78,60,88,59,64,67],
},
columns=["姓名","语文","数学","英语","物理","化学","生物","历史","地理","政治","技术"])
print(df1)

输出结果:
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 高明 93 98 96 43 74 71 66 57 44 85
1 章鱼 109 145 105 58 41 78 52 63 41 78
2 地心 103 143 134 95 64 93 41 69 42 60
3 琐碎 125 134 119 68 52 78 52 84 65 88
4 石宝 118 122 105 79 74 77 57 51 48 59
5 二哥 113 103 135 67 52 60 50 51 48 64
6 如意 98 67 90 45 58 64 59 62 49 67

这是我们通过字典来构建DataFrame对象的。老师觉得手动输入很麻烦,那么我们也可以从Excel表格或者CSV表格中导入数据。

从外部数据构建DataFrame

这是从Excel表格导入的。注意,表格文件要和python文件位于同一个文件夹。

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
df2=pd.read_excel("成绩.xlsx") #从Excel表格导入
print(df2)

输出结果:
Unnamed: 0 姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 0 高明 93 98 96 43 74 71 66 57 44 85
1 1 章鱼 109 145 105 58 41 78 52 63 41 78
2 2 地心 103 143 134 95 64 93 41 69 42 60
3 3 琐碎 125 134 119 68 52 78 52 84 65 88
4 4 石宝 118 122 105 79 74 77 57 51 48 59
5 5 二哥 113 103 135 67 52 60 50 51 48 64
6 6 如意 98 67 90 45 58 64 59 62 49 67

如果你是想从CSV表格导入,也没有问题。

1
2
3
4
5
6
7
8
9
10
11
12
df2=pd.read_csv("成绩.csv")
print(df2)

输出结果:
Unnamed: 0 姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 0 高明 93 98 96 43 74 71 66 57 44 85
1 1 章鱼 109 145 105 58 41 78 52 63 41 78
2 2 地心 103 143 134 95 64 93 41 69 42 60
3 3 琐碎 125 134 119 68 52 78 52 84 65 88
4 4 石宝 118 122 105 79 74 77 57 51 48 59
5 5 二哥 113 103 135 67 52 60 50 51 48 64
6 6 如意 98 67 90 45 58 64 59 62 49 67

如果导入过程中出现乱码,记得加上UTF-8编码扩展

1
2
df2=pd.read_csv("成绩.csv",encoding='UTF8')
print(df2)

导出DataFrame数据

老师处理完数据,需要导出。导出只用到两个函数,分别是to_excel()和to_csv()。在使用的时候一定要记得加上扩展名。

1
2
df1.to_csv("成绩.csv")
df1.to_excel("成绩.xlsx")

导出的时候控制台不会有显示。如果已经有这个文件,那么在导出的时候会把原先的文件覆盖掉。

DataFrame对象常用属性

这一小节就是抄课本啦嘿嘿

属性 说明
index DataFrame的行索引
columns 存放各列的列标题
values 存放值的二维数据
T 行列转置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
for i in df1.index:     #输出DataFrame的行索引
print(i)
print("我是可爱的分隔符~")
for i in df1.columns: #输出DataFrame的列索引
print(i)
print("我是可爱的分隔符~")
for i in df1.values: #输出DataFrame中的所有值
print(i)
print("我是可爱的分隔符~")
df1.T #行列转置
print("我是可爱的分隔符~")
print(df1)
print("我是可爱的分隔符~")
print(df1.T)

输出结果:
0
1
2
3
4
5
6
我是可爱的分隔符~
姓名
语文
数学
英语
物理
化学
生物
历史
地理
政治
技术
我是可爱的分隔符~
['高明' 93 98 96 43 74 71 66 57 44 85]
['章鱼' 109 145 105 58 41 78 52 63 41 78]
['地心' 103 143 134 95 64 93 41 69 42 60]
['琐碎' 125 134 119 68 52 78 52 84 65 88]
['石宝' 118 122 105 79 74 77 57 51 48 59]
['二哥' 113 103 135 67 52 60 50 51 48 64]
['如意' 98 67 90 45 58 64 59 62 49 67]
我是可爱的分隔符~
我是可爱的分隔符~
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 高明 93 98 96 43 74 71 66 57 44 85
1 章鱼 109 145 105 58 41 78 52 63 41 78
2 地心 103 143 134 95 64 93 41 69 42 60
3 琐碎 125 134 119 68 52 78 52 84 65 88
4 石宝 118 122 105 79 74 77 57 51 48 59
5 二哥 113 103 135 67 52 60 50 51 48 64
6 如意 98 67 90 45 58 64 59 62 49 67
我是可爱的分隔符~
0 1 2 3 4 5 6
姓名 高明 章鱼 地心 琐碎 石宝 二哥 如意
语文 93 109 103 125 118 113 98
数学 98 145 143 134 122 103 67
英语 96 105 134 119 105 135 90
物理 43 58 95 68 79 67 45
化学 74 41 64 52 74 52 58
生物 71 78 93 78 77 60 64
历史 66 52 41 52 57 50 59
地理 57 63 69 84 51 51 62
政治 44 41 42 65 48 48 49
技术 85 78 60 88 59 64 67

我提醒一下,在DataFrame里面,很多函数都不会直接作用于执行对象,而是返回另一个对象。就像上面的例子中,虽然执行过df1.T,但事实上没有输出,并且df1中的数据也没有改变,因为它返回了一个对象。

说明: append(、drop(丽数均不改变原有df对象中的数据,而是通过返回另一个DataFrame对象来存放改变后的数据。

引用、更改DataFrame中的数据

不抄课本了,举例子举例子。

通过属性检索列

高明同学想看有哪些同学参与成绩分析,于是她输入代码:

1
2
3
4
5
6
7
8
9
10
11
print(df1.姓名)     #通过属性检索列

输出结果:
0 高明
1 章鱼
2 地心
3 琐碎
4 石宝
5 二哥
6 如意
Name: 姓名, dtype: object

通过字典记法检索

列她还可以这么输入代码:

1
2
3
4
5
6
7
8
9
10
11
print(df1["姓名"])    #通过字典记法检索列

输出结果:
0 高明
1 章鱼
2 地心
3 琐碎
4 石宝
5 二哥
6 如意
Name: 姓名, dtype: object

两种方法都是检索“姓名”这个columns里的所有数据。

还可以只查看前面几位同学的名字,那就得这样输入:

1
2
3
4
5
6
7
8
9
10
print(df1.姓名[1])
print("我是可爱的分隔符~")
print(df1["姓名"][1:3])

输出结果:
章鱼
我是可爱的分隔符~
1 章鱼
2 地心
Name: 姓名, dtype: object

按columns来更改数据

老师发现如意同学的成绩输错了,化学成绩多加了十分,所以要更改数据。

1
2
3
4
5
6
df1.化学=[74,41,64,52,74,52,48]
print(df1[df1['姓名']=='如意'])

输出结果:
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
6 如意 98 67 90 45 48 64 59 62 49 67

可以看到,老师把成绩改回来了。

检索条件

提醒一下,引用符合条件的值,需要这样引用:print(df1[df1['姓名']=='如意'])
如果需要多个全部符合条件的值(和),需要这样引用:print(df1[(df1['姓名']=='如意') & (df1['化学']==48)])
如果需要检索符合其中一个条件的值(或),需要这样引用:print(df1[(df1['姓名']=='如意') | (df1['政治']==48)])
多个条件的时候,每个条件都要用小括号括起来!!!
老师需要查找如意同学或政治考48的同学:

1
2
3
4
5
6
7
print(df1[(df1['姓名']=='如意') | (df1['政治']==48)])

输出结果:
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
4 石宝 118 122 105 79 74 77 57 51 48 59
5 二哥 113 103 135 67 52 60 50 51 48 64
6 如意 98 67 90 45 48 64 59 62 49 67

啊哈,还有石宝和二哥政治考了48。

如果没有符合检索条件的项,那么就会输出空的DataFrame:

1
2
3
4
5
6
print(df1[(df1['姓名']=='如意') & (df1['政治']==48)])

输出结果:
Empty DataFrame
Columns: [姓名, 语文, 数学, 英语, 物理, 化学, 生物, 历史, 地理, 政治, 技术]
Index: []

当然我们还可以找找数学不及格的同学,这个时候“==”符号就改成了“<”符号:

1
2
3
4
5
print(df1[df1['数学']<90])

输出结果:
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
6 如意 98 67 90 45 48 64 59 62 49 67

at[]函数

章鱼想查一下自己数学考了多少,那么我们需要用到at[]函数:(当然章鱼同学已经知道了自己的索引号)

1
2
3
4
print(df1.at[1,'数学'])

输出结果:
145

哇,章鱼真的是数学学霸!!!
章鱼同学在数学竞赛中荣获二等奖,学校决定在他的数学成绩上加5分:

1
2
3
4
5
df1.at[1,'数学'] = 150 
print(df1.at[1,'数学'])

输出结果:
150

所以还可以使用at函数直接修改单个值,省去了整列或者整行数据输入的麻烦。

DataFrame常用函数介绍

我又抄课本了

函数 说明
count() 返回非空(NaN)数据项的数量
sum()、mean() 求和、求平均值,通过axis=0/1 确定行列
max()、min() 返回最大、最小值
describe() 返回各列的基本描述统计值,包含计数、平均数、标准差、最大值、最小值及4分位差
head()、tail() 返回DataFrame的前n个、后n个数据记录
groupby() 对各列或各行中的数据进行分组,然后可对其中每一组数据进行不同的操作
sort_ values() 排序,通过axis=0/1 确定行列
drop() 删除数据,通过axis=0/1确定行列
append() 在指定元素的结尾插入内容
insert() 在指定位置插入列
rename() 修改列名或者索引
concat() 合并DataFrame对象
set_ value() 根据行标签和列标签设置单个值
plot() 绘图

count()函数

老师检查一下有没有人缺考,就用count(),如果每门课考试人数都是7,或者每个人考试次数都是11,那么就没有同学缺考。表格中已经写得很清楚了,统计非空数据项的个数。当然它可以以index为坐标统计,也可以以columns为坐标统计。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
print(df1.count())                #统计每个column下的数据 
print(df1.count(axis='columns')) #统计每个index下的数据

输出结果:
姓名 7
语文 7
数学 7
英语 7
物理 7
化学 7
生物 7
历史 7
地理 7
政治 7
技术 7
dtype: int64
0 11
1 11
2 11
3 11
4 11
5 11
6 11
dtype: int64

sum()和mean()函数

老师统计一下每个人的总分和每门课的平均分。这里我们会用到sum()和mean()函数。默认中,这两个函数都是对每个columns取和/平均值,也就是默认axis=0。如果要对每个index取和/平均值,axis就要=1,或者axis=’columns’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
print(df1.sum(axis=1))
#当然还可以这样写:print(df1.sum(axis='columns'))
print(df1.mean())


输出结果:
c:\Users\Administrator\Desktop\pandas_text.py:26: FutureWarning: Dropping of nuisance columns in DataFrame reductions (with 'numeric_only=None') is deprecated; in a future version this will raise TypeError. Select only valid columns before calling the reduction.
print(df1.sum(axis=1))
0 727
1 775
2 844
3 865
4 790
5 743
6 649
dtype: int64
c:\Users\Administrator\Desktop\pandas_text.py:27: FutureWarning: Dropping of nuisance columns in DataFrame reductions (with 'numeric_only=None') is deprecated; in a future version this will raise TypeError. Select only valid columns before calling the reduction.
print(df1.mean())
语文 108.428571
数学 116.714286
英语 112.000000
物理 65.000000
化学 57.857143
生物 74.428571
历史 53.857143
地理 62.428571
政治 48.142857
技术 71.571429
dtype: float64

max()、min()函数

老师查看每个门课的最高分和最低分。默认axis=0.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
print(df1.min())
print(df1.max())

输出结果:
姓名 二哥
语文 93
数学 67
英语 90
物理 43
化学 41
生物 60
历史 41
地理 51
政治 41
技术 59
dtype: object
姓名 高明
语文 125
数学 150
英语 135
物理 95
化学 74
生物 93
历史 66
地理 84
政治 65
技术 88
dtype: object

describe()函数

这个函数考试就不会来考了吧describe函数返回的是一个DataFrame对象,当然也可以用和df1一样的函数print(df1.describe().describe()),但是这样就很没意义了(滑稽)。

1
2
3
4
5
6
7
8
9
10
11
12
print(df1.describe())

输出结果:
语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
count 7.000000 7.000000 7.00000 7.000000 7.000000 7.000000 7.000000 7.000000 7.000000 7.000000
mean 108.428571 116.714286 112.00000 65.000000 57.857143 74.428571 53.857143 62.428571 48.142857 71.571429
std 11.282097 29.255850 17.79513 18.448125 12.966991 10.845232 7.861903 11.544943 8.071113 11.984116
min 93.000000 67.000000 90.00000 43.000000 41.000000 60.000000 41.000000 51.000000 41.000000 59.000000
25% 100.500000 100.500000 100.50000 51.500000 50.000000 67.500000 51.000000 54.000000 43.000000 62.000000
50% 109.000000 122.000000 105.00000 67.000000 52.000000 77.000000 52.000000 62.000000 48.000000 67.000000
75% 115.500000 138.500000 126.50000 73.500000 69.000000 78.000000 58.000000 66.000000 48.500000 81.500000
max 125.000000 150.000000 135.00000 95.000000 74.000000 93.000000 66.000000 84.000000 65.000000 88.000000

head()、tail()函数

这个是常考点。head()、tail()函数分别返回DataFrame的首/末几行。使用的时候也可以用df[:3]或者df[:-4]输出前/后3行内容。

如果head()中没有任何数字,那么默认是返回前5行。如果head()中是负数,比如head(-2),那就相当与df[:-2]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
print(df1.head())
print(df1.head(2))
print(df1.head(-2))
print(df1[:2])

输出结果:
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 高明 93 98 96 43 74 71 66 57 44 85
1 章鱼 109 150 105 58 41 78 52 63 41 78
2 地心 103 143 134 95 64 93 41 69 42 60
3 琐碎 125 134 119 68 52 78 52 84 65 88
4 石宝 118 122 105 79 74 77 57 51 48 59
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 高明 93 98 96 43 74 71 66 57 44 85
1 章鱼 109 150 105 58 41 78 52 63 41 78
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 高明 93 98 96 43 74 71 66 57 44 85
1 章鱼 109 150 105 58 41 78 52 63 41 78
2 地心 103 143 134 95 64 93 41 69 42 60
3 琐碎 125 134 119 68 52 78 52 84 65 88
4 石宝 118 122 105 79 74 77 57 51 48 59
姓名 语文 数学 英语 物理 化学 生物 历史 地理 政治 技术
0 高明 93 98 96 43 74 71 66 57 44 85
1 章鱼 109 150 105 58 41 78 52 63 41 78