学习python数据分析 四 pandas (1)

Pandas是使用Python语言开发的用于数据处理和数据分析的第三方库。它擅长处理数字型数据和时间序列数据,当然文本型的数据也能轻松处理。

Pandas由Wes McKinney于2008年开发。McKinney当时在纽约的一家金融服务机构工作,金融数据分析需要一个健壮和超快速的数据分析
工具,于是他就开发出了Pandas。Pandas的命名跟熊猫无关,而是来自计量经济学中的术语“面板数据”(Panel data)。

安装

1
2
pip install pandas xlrd openpyxl

数据结构

  1. Series
    一系列数据
  2. DataFrame

加载数据

pandas支持多种数据源,包括excel,csv,html,sql等。这里我们加载一个学生成绩的样本数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pandas as pd
df = pd.read_excel('https://www.gairuo.com/file/data/dataset/team.xlsx')
df

name team Q1 Q2 Q3 Q4
0 Liver E 89 21 24 64
1 Arry C 36 37 37 57
2 Ack A 57 60 18 84
3 Eorge C 93 96 71 78
4 Oah D 65 49 61 86
... ... ... ... ... ... ...
95 Gabriel C 48 59 87 74
96 Austin7 C 21 31 30 43
97 Lincoln4 C 98 93 1 20
98 Eli E 11 74 58 91
99 Ben E 21 43 41 74
100 rows × 6 columns

这里读excel返回一个DataFrame对象,pandas的绝大部分API都围绕着DataFrame对象。有点类似numpy的ndarray但又有非常大的区别:

ndarray和DataFrame的区别

NumPy的ndarray和Pandas的DataFrame是两种不同的数据结构。

  • ndarray是一个多维数组对象,用于存储同类型元素的多维数据,可以进行高效的数学运算,如线性代数、傅里叶变换、随机数生成等。NumPy的ndarray是内存连续的,并且能够支持向量化运算,这使得对于大型数据集的计算非常高效。

  • DataFrame是一种二维表格数据结构,由多个Series组成。每个Series都是一个单独的列,不同的Series可以有不同的数据类型。DataFrame提供了各种数据操作功能,如过滤、排序、统计等,可以方便地进行数据分析和处理。

相比之下,DataFrame具有更强大的数据操作和分析能力,但在执行数学运算时可能不如ndarray高效。通常,ndarray更适合进行数值计算和科学计算,而DataFrame则更适合进行数据分析和处理。

查看数据

  1. df.head() 查看前x行
  2. df.tail() 查看末x行
  3. df.sample() 随机选择

查看DataFrame的元信息

1
2
3
df.shape

(100, 6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 name 100 non-null object
1 team 100 non-null object
2 Q1 100 non-null int64
3 Q2 100 non-null int64
4 Q3 100 non-null int64
5 Q4 100 non-null int64
dtypes: int64(4), object(2)
memory usage: 4.8+ KB

查看列的类型

1
2
3
4
5
6
7
8
9

df.dtypes
name object
team object
Q1 int64
Q2 int64
Q3 int64
Q4 int64
dtype: object

配置索引

  • 索引(index):行和列上的标签,标识二维数据坐标的行索引和列索引,默认情况下,指的是每一行的索引。如果是Series,那只能是它行上的索引。列索引又被称为字段名、表头。
  • 自然索引、数字索引:行和列的0~n(n为数据长度–1)形式的索引,数据天然具有的索引形式。虽然可以指定为其他名称,但在有些方法中依然可以使用。
  • 标签(label):行索引和列索引,如果是Series,那只能是它行上的索引。
  • 轴(axis):仅用在DataFrame结构中,代表数据的方向,如行和列,用0代表列(默认),1代表行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    df.set_index('name')

    team Q1 Q2 Q3 Q4
    name
    Liver E 89 21 24 64
    Arry C 36 37 37 57
    Ack A 57 60 18 84
    Eorge C 93 96 71 78
    Oah D 65 49 61 86
    ... ... ... ... ... ...
    Gabriel C 48 59 87 74
    Austin7 C 21 31 30 43
    Lincoln4 C 98 93 1 20
    Eli E 11 74 58 91
    Ben E 21 43 41 74
    100 rows × 5 columns\
    这样已经看不到之前的0-100的索引了。但是要注意
  1. 这种方式生成的索引是创建一个新的DF对象,原有的df并没有发生变化,如果要修改原有的需要添加inPlace参数。
  2. 需要注意 配置完索引后,原字段已经不在column中了,所以
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    df = df.set_index()
    df.info()

    <class 'pandas.core.frame.DataFrame'>
    Index: 100 entries, Liver to Ben
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 team 100 non-null object
    1 Q1 100 non-null int64
    2 Q2 100 non-null int64
    3 Q3 100 non-null int64
    4 Q4 100 non-null int64
    dtypes: int64(4), object(1)
    memory usage: 8.8+ KB
    这时我们使用 df[‘name’] 是不能读取name这一列的。想要读取索引可以df.index。

选择数据

  1. 直接访问
    选择Q2 Q3 两列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    df[['Q2','Q3']]

    Q2 Q3
    0 21 24
    1 37 37
    2 60 18
    3 96 71
    4 49 61
    ... ... ...
    95 59 87
    96 31 30
    97 93 1
    98 74 58
    99 43 41
    100 rows × 2 columns
  2. 自然索引

    1
    2
    3
    4
    5
    6
    7
    df[0:3]

    team Q1 Q2 Q3 Q4
    name
    Liver E 89 21 24 64
    Arry C 36 37 37 57
    Ack A 57 60 18 84

从1,2可以看出df[]如果传入的是列名或者一个列名的list则作为列的查询,如果传入的是一个range则作为行选择处理。

  1. loc
    df.loc[x, y]是一个非常强大的数据选择函数,其中x代表行,y代表列,行和列都支持条件表达式,也支持类似列表那样的切片(如果要用自然索引,需要用df.iloc[])
1
2
3
# 选择多列
df[['team', 'Q1']] # 只看这两列,注意括号
df.loc[:, ['team', 'Q1']] # 和上一行效果一样
  1. iloc
    同样是iloc[x,y] 这里则只支持自然索引,不支持条件

比如选择前10列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
df.iloc[:10,:]

team Q1 Q2 Q3 Q4
name
Liver E 89 21 24 64
Arry C 36 37 37 57
Ack A 57 60 18 84
Eorge C 93 96 71 78
Oah D 65 49 61 86
Harlie C 24 13 87 43
Acob B 61 95 94 8
Lfie A 9 10 99 37
Reddie D 64 93 57 72
Oscar A 77 9 26 67# 选择多列
df[['team', 'Q1']] # 只看这两列,注意括号
df.loc[:, ['team', 'Q1']] # 和上一行效果一样

排序

df.sort_values([{要排序的列}],ascending=[{这些列是否升序}])

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
## 多字段排序
df.sort_values(['team', 'Q1'], ascending=[True, False])排序公式
team Q1 Q2 Q3 Q4
name
Aaron A 96 75 55 8
Henry A 91 15 75 17
Nathan A 87 77 62 13
Dylan A 86 87 65 20
Blake A 78 23 93 9
... ... ... ... ... ...
Eli E 11 74 58 91
Jude E 8 45 13 65
Rory9 E 8 12 58 27
Jackson5 E 6 10 15 33
Finn E 4 1 55 32

聚合

groupby将返回一个DataFrameGroupBy对象
我们可以查看每组的大小

1
2
3
4
5
6
7
8
9
10
df.groupby('team').size()


team
A 17
B 22
C 22
D 19
E 20
dtype: int64

分组完毕要选择聚合算法。

常见的聚合算法是sum(加和)、mean(均值)

1
2
3
4
5
6
7
8
9
df.groupby('team').sum()

Q1 Q2 Q3 Q4

1066 639 875 783
975 1218 1202 1136
1056 1194 1068 1127
860 1191 1241 1199
963 1013 881 1033

也可以使用agg函数聚合多个列

1
2
3
4
5
6
7
8
9
10
11
12
13
df.groupby('team').agg({'Q1': sum, # 总和
'Q2': 'count', # 总数
'Q3':'mean', # 平均
'Q4': max}) # 最大值


Q1 Q2 Q3 Q4
team
A 1066 17 51.470588 97
B 975 22 54.636364 99
C 1056 22 48.545455 98
D 860 19 65.315789 99
E 963 20 44.050000 98

偏移

diff

跟numpy中的语义相同
比如查看所有学生Q1 到 Q4 每季度成绩增长

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
df.loc[:,'Q1':'Q4'].diff(1, axis=1)

Q1 Q2 Q3 Q4

NaN -68 3 40
NaN 1 0 20
NaN 3 -42 66
NaN 3 -25 7
NaN -16 12 25
... ... ... ...
NaN 11 28 -13
NaN 10 -1 13
NaN -5 -92 19
NaN 63 -16 33
NaN 22 -2 33

shift

向下移动,实际上索引不会动,其他列全部下移一位

1
2
3
4
5
6
7
8
9
10
df.shift().tail()


team Q1 Q2 Q3 Q4
name
Gabriel D 20.0 31.0 62.0 68.0
Austin7 C 48.0 59.0 87.0 74.0
Lincoln4 C 21.0 31.0 30.0 43.0
Eli C 98.0 93.0 1.0 20.0
Ben E 11.0 74.0 58.0 91.0

向上移动

1
2
3
4
5
6
7
8
df.shift().head()
team Q1 Q2 Q3 Q4
name
Liver None NaN NaN NaN NaN
Arry E 89.0 21.0 24.0 64.0
Ack C 36.0 37.0 37.0 57.0
Eorge A 57.0 60.0 18.0 84.0
Oah C 93.0 96.0 71.0 78.0

计算

DataFrame可以执行常见的运算符+-*/|&

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
df[['Q1','Q2']]*2

Q1 Q2
name
Liver 178 42
Arry 72 74
Ack 114 120
Eorge 186 192
Oah 130 98
... ... ...
Gabriel 96 118
Austin7 42 62
Lincoln4 196 186
Eli 22 148
Ben 42 86

两个矩阵相加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
df['Q1']+df['Q2']


name
Liver 110
Arry 73
Ack 117
Eorge 189
Oah 114
...
Gabriel 107
Austin7 52
Lincoln4 191
Eli 85
Ben 64
Length: 100, dtype: int64

这里相加的行为根据元数据类型不同结果也不同。

条件判断表达式会转换为矩阵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
df['Q1']>80

0 True
1 False
2 False
3 True
4 False
...
95 False
96 False
97 True
98 False
99 False
Name: Q1, Length: 100, dtype: bool

我们又可以使用产生的矩阵选择数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
df[df['Q1']>80]

name team Q1 Q2 Q3 Q4
0 Liver E 89 21 24 64
3 Eorge C 93 96 71 78
12 Archie C 83 89 59 68
17 Henry A 91 15 75 17
19 Max E 97 75 41 3
25 Harrison B 89 13 18 75
32 Alexander C 91 76 26 79
33 Adam C 90 32 47 39
36 Jaxon E 88 98 19 98
38 Elijah B 97 89 15 46
42 Dylan A 86 87 65 20
70 Nathan A 87 77 62 13
77 Michael B 89 21 59 92
80 Ryan E 92 70 64 31
83 Albert0 B 85 38 41 17
88 Aaron A 96 75 55 8
97 Lincoln4 C 98 93 1 20

比如我们可以查连续4季度增长的:

1
2
3
4
5
6
7
8
9
df[(df['Q1'] < df['Q2']) & (df['Q2'] < df['Q3']) & (df['Q3'] < df['Q4'])]

team Q1 Q2 Q3 Q4
name
Zachary E 12 71 85 93
Jackson E 6 10 15 33
Harvey2 B 43 76 87 90
Elliott B 9 31 33 60
Aiden D 20 31 62 68

query表达式

如果只做列的操作可以这样:

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
df.query('Q1<Q2<Q3<Q4')

team Q1 Q2 Q3 Q4
name
Zachary E 12 71 85 93
Jackson5 E 6 10 15 33
Harvey2 B 43 76 87 90
Elliott B 9 31 33 60
Aiden D 20 31 62 68

df.query('Q1 + Q2 > 180')

team Q1 Q2 Q3 Q4
name
Eorge C 93 96 71 78
Jaxon E 88 98 19 98
Elijah B 97 89 15 46
Lincoln4C 98 93 1 20

df.query('team !="C"')

team Q1 Q2 Q3 Q4
name
Liver E 89 21 24 64
Ack A 57 60 18 84
Oah D 65 49 61 86
Acob B 61 95 94 8
Lfie A 9 10 99 37
... ... ... ... ... ...
Grayson7B 59 84 74 33
Jamie0 B 39 97 84 55
Aiden D 20 31 62 68
Eli E 11 74 58 91
Ben E 21 43 41 74
78 rows × 5 columns
  • 本文作者: fenix
  • 本文链接: https://fenix0.com/py-sci-04/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC 许可协议。转载请注明出处!