Python之Pandas详解

八秒记忆的老男孩 2024-08-02 16:33:06 阅读 99

<code>Pandas是Python语言的一个扩展程序库,用于数据分析。

Pandas是一个开放源码、BSD许可的库,提供高性能、易于使用的数据结构和数据分析工具。

Pandas名字衍生自术语 “panel data”(面板数据)和 “Python data analysis”(Python数据分析)。

Pandas一个强大的分析结构化数据的工具集,基础是NumPy(提供高性能的矩阵运算)。

Pandas可以从各种文件格式比如CSVJSONSQLMicrosoft Excel 导入数据。

Pandas可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。

Pandas广泛应用在学术、金融、统计学等各个数据分析领域。

Pandas主要包括以下几个特点:

它提供了一个简单、高效、带有默认标签(也可以自定义标签)的DataFrame对象。能够快速从不同格式的文件中加载数据(比如 ExcelCSVSQL文件),然后转换为可处理的对象;能够按数据的行、列标签进行分组,并对分组后的对象执行聚合和转换操作;能够很方便地实现数据归一化操作和缺失值处理;能够很方便地对DataFrame的数据列进行增加、修改或者删除的操作;能够处理不同格式的数据集,比如矩阵数据、异构数据表、时间序列等;提供了多种处理数据集的方式,比如构建子集、切片、过滤、分组以及重新排序等。

⛄Pandas数据结构

Pandas的主要数据结构是Series(一维数据)与DataFrame(二维数据),这两种数据结构足以处理金融、统计、社会科学、工程等领域里的大多数典型用例。

Series是一种类似于一维数组的对象,它由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成。

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共同用一个索引)。

⛄Pandas Series

Pandas Series类似表格中的一个列(column),类似于一维数组,由一组数据值(value)和一组标签组成,其中标签与数据值之间是一一对应的关系。Series可以保存任何数据类型,比如整数、字符串、浮点数、Python对象等,它的标签默认为整数,从0开始依次递增。

👀创建Series对象

Series由索引(index)和列组成,函数如下:

pandas.Series(data, index, dtype, name, copy)

参数说明:

data:一组数据(ndarray类型)。

index:数据索引标签,如果不指定,默认从0开始。

dtype:数据类型,默认会自己判断。

name:设置名称。

copy:拷贝数据,默认为False。

import pandas as pd

a = [1, 2, 3]

myvar = pd.Series(a)

print(myvar)

print(myvar[1])

# 输出结果:第一列为索引,第二列为数据

# 如果没有指定索引,索引值就从0开始,我们可以根据索引值读取数据:

0 1

1 2

2 3

dtype: int64

2

我们也可以使用数组、字典、标量值或者Python对象来创建Series对象。

(1)创建一个空Series对象

import pandas as pd

#输出数据为空

s = pd.Series()

print(s)

# 输出结果

Series([], dtype: float64)

(2)ndarray创建Series对象

ndarrayNumPy中的数组类型,当datandarry时,传递的索引必须具有与数组相同的长度。如果没有指定索引(隐式索引),索引值就从0开始(索引值将使用是range(n) 生成,其中n代表数组长度);我们可以根据索引值读取数据。可以指定索引值(显式索引),如下实例。

import pandas as pd

import numpy as np

# 指定索引值

a = np.array(["Google", "Runoob", "Wiki"])

myvar = pd.Series(a, index = ["x", "y", "z"])

print(myvar)

print(myvar["y"])

#输出结果

x Google

y Runoob

z Wiki

dtype: object

Runoob

(3)dict创建Series对象

我们也可以使用key/value对象,类似字典来创建Series

import pandas as pd

# 使用字典创建Series

# 没有传递索引,字典的key变成了索引值。

sites = { 1: "Google", 2: "Runoob", 3: "Wiki"}

myvar1 = pd.Series(sites)

print(myvar1)

# 如果我们只需要字典中的一部分数据,只需要指定需要数据的索引即可,如下实例:

myvar2 = pd.Series(sites, index = [1,2])

print(myvar2)

# 当传递的索引值无法找到与其对应的值时,使用NaN(非数字)填充。

myvar3 = pd.Series(sites, index = [1,3,2,4])

print(myvar3)

# 输出结果

1 Google

2 Runoob

3 Wiki

dtype: object

1 Google

2 Runoob

dtype: object

1 Google

3 Wiki

2 Runoob

4 NaN

dtype: object

当传递的索引值无法找到与其对应的值时,使用NaN(非数字)填充。

(4)标量创建Series对象

如果data是标量值,则必须提供索引,示例如下:

import pandas as pd

s = pd.Series(5, index = [0,1,2,3])

print(s)

# 输出结果

0 5

1 5

2 5

3 5

dtype: int64

标量值按照index的数量进行重复,并与其一一对应。

设置Series名称参数:

import pandas as pd

sites = { 1: "Google", 2: "Runoob", 3: "Wiki"}

myvar = pd.Series(sites, index = [1, 2], name="RUNOOB-Series-TEST" )code>

print(myvar)

# 输出结果

1 Google

2 Runoob

Name: RUNOOB-Series-TEST, dtype: object

👀访问Series数据

(1)位置索引访问

这种访问方式与ndarraylist相同,使用元素自身的下标进行访问。我们知道数组的索引计数从0开始,这表示第一个元素存储在第0个索引位置上,以此类推,就可以获得Series序列中的每个元素。

import pandas as pd

s = pd.Series([5,2,3,4,5],index = ['a','b','c','d','e'])

print(s[0]) # 位置下标

print(s['a']) # 标签下标

# 通过切片的方式访问Series序列中的数据

print(s[:3])

# 获取最后三个元素

print(s[-3:])

# 输出结果

5

5

a 5

b 2

c 3

dtype: int64

c 3

d 4

e 5

dtype: int64

(2)索引标签访问

Series类似于固定大小的dict,把index中的索引标签当做key,而把Series序列中的元素值当做value,然后通过index索引标签来访问或者修改元素值。

import pandas as pd

# 使用索标签访问单个元素值

s = pd.Series([16,17,18,19,20],index = ['a','b','c','d','e'])

print(s['a'])

# 使用索引标签访问多个元素值

print(s[['a','c','d']])

# 如果使用了index中不包含的标签,则会触发异常

print(s['f'])

# 输出结果

16

a 16

c 18

d 19

dtype: int64

......

KeyError: 'f'

👀Series常用属性

Series的常用属性和方法:

名称 属性
axes 以列表的形式返回所有行索引标签
dtype 返回对象的数据类型
empty 返回一个空的Series对象
ndim 返回输入数据的维数
size 返回输入数据的元素数量
values ndarray的形式返回Series对象
index 返回一个RangeIndex对象,用来描述索引的取值范围

import pandas as pd

import numpy as np

s = pd.Series(np.random.randn(6))

print(s)

print("*"*20)

# axes属性

print(s.axes)

print("*"*20)

# dtype属性

print(s.dtype)

print("*"*20)

# empty

print(s.empty)

print("*"*20)

# ndim,Series是一维数据结构,因此它始终返回1

print(s.ndim)

print("*"*20)

# size返回Series对象的大小(长度)

print(s.size)

print("*"*20)

# value以数组的形式返回Series对象中的数据

print(s.values)

print("*"*20)

# index该属性用来查看Series中索引的取值范围

#显示索引

s1 = pd.Series([1,2,5,8],index = ['a','b','c','d'])

print(s1.index)

#隐式索引

s2 = pd.Series([1,2,5,8])

print(s2.index)

# 输出结果

0 -0.674501

1 1.030106

2 -1.636359

3 -1.540996

4 1.312837

5 -0.735986

dtype: float64

********************

[RangeIndex(start=0, stop=6, step=1)]

********************

float64

********************

False

********************

1

********************

6

********************

[-0.67450078 1.03010573 -1.63635856 -1.54099596 1.31283698 -0.73598645]

********************

Index(['a', 'b', 'c', 'd'], dtype='object')code>

RangeIndex(start=0, stop=4, step=1)

👀Series常用方法

(1)head()&tail()查看数据

如果想要查看Series的某一部分数据,可以使用head()或者tail()方法。其中head()返回前n行数据,默认显示前5行数据。tail()返回的是后n行数据,默认为后5行。

import pandas as pd

import numpy as np

s = pd.Series(np.random.randn(5))

print (s)

# 返回前三行数据

print(s.head(3))

# 返回后两行数据

print(s.tail(3))

# 输出结果

0 -0.264915

1 -1.120671

2 0.621638

3 -0.449170

4 0.533876

dtype: float64

0 -0.264915

1 -1.120671

2 0.621638

dtype: float64

2 0.621638

3 -0.449170

4 0.533876

dtype: float64

(2)isnull()&notnull()检测缺失值

isnull()notnull()用于检测Series中的缺失值。所谓缺失值,顾名思义就是值不存在、丢失、缺少。

isnull():如果为值不存在或者缺失,则返回Truenotnull():如果值不存在或者缺失,则返回False

其实不难理解,在实际的数据分析任物中,数据的收集往往要经历一个繁琐的过程。在这个过程中难免会因为一些不可抗力,或者人为因素导致数据丢失的现象。这时,我们可以使用相应的方法对缺失值进行处理,比如均值插值、数据补齐等方法。上述两个方法就是帮助我们检测是否存在缺失值。

import pandas as pd

#None代表缺失数据

s = pd.Series([1,6,None,8,None])

print(pd.isnull(s)) #是空值返回True

print(pd.notnull(s)) #空值返回False

# 输出结果

0 False

1 False

2 True

3 False

4 True

dtype: bool

0 True

1 True

2 False

3 True

4 False

dtype: bool

⛄Pandas DataFrame

DataFrame是表格型的数据结构,既有行标签(index),又有列标签(columns),它也被称异构数据表。

它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共同用一个索引),每一行数据都可以看成一个Series结构,DataFrame为这些行中每个数据值增加了一个列标签。

Series一样,DataFrame自带行标签索引,默认为“隐式索引”即从0开始依次递增,行标签与DataFrame中的数据项一一对应。DataFrame数据结构的特点:

DataFrame每一列的标签值允许使用不同的数据类型;DataFrame是表格型的数据结构,具有行和列;DataFrame中的每个数据值都可以被修改;DataFrame结构的行数、列数允许增加或者删除;DataFrame有两个方向的标签轴,分别是行标签和列标签;DataFrame可以对行和列执行算术运算。

👀创建DF对象

DataFrame构造方法如下:

pandas.DataFrame(data, index, columns, dtype, copy)

参数说明:

data:一组数据(ndarray、series, map, lists, dict等类型)。

index:索引值,或者可以称为行标签。

columns:列标签,默认为RangeIndex(0, 1, 2, …, n) 。

dtype:数据类型。

copy:拷贝数据,默认为False。

Pandas DataFrame是一个二维的数组结构,类似二维数组。

Pandas提供了多种创建DataFrame对象的方式,主要包含以下五种:

(1)创建空的DataFrame对象

import pandas as pd

df = pd.DataFrame()

print(df)

# 输出结果

Empty DataFrame

Columns: []

Index: []

(2)列表创建DataFame对象

可以使用单一列表或嵌套列表来创建一个DataFrame

import pandas as pd

# 单一列表创建DataFrame对象

data1 = [6,7,8,9,10]

df1 = pd.DataFrame(data1)

print(df1)

# 嵌套列表创建DataFrame对象,并指定数值元素的数据类型为float

data2 = [['Google',10],['Runoob',12],['Wiki',13]]

df2 = pd.DataFrame(data2,columns = ['Site','Age'],dtype = float)

print(df2)

# 输出结果

0

0 6

1 7

2 8

3 9

4 10

Site Age

0 Google 10.0

1 Runoob 12.0

2 Wiki 13.0

(3)字典嵌套列表创建DataFame对象

dict字典中,键对应的值的元素长度必须相同(也就是列表长度相同)。如果传递了索引,那么索引的长度应该等于数组的长度;如果没有传递索引,那么默认情况下,索引将是range(n),其中n代表数组长度。

import pandas as pd

# 这里使用了默认行标签,也就是range(n)。它生成了0,1,2,3,并分别对应了列表中的每个元素值

data = { 'Site':['Google', 'Runoob', 'Wiki'], 'Age':[10, 12, 13]}

df = pd.DataFrame(data)

print(df)

# 添加自定义的行标签,index参数为每行分配了一个索引

df2 = pd.DataFrame(data,index = ['one','two','three'])

print(df2)

# 输出结果

Site Age

0 Google 10

1 Runoob 12

2 Wiki 13

Site Age

one Google 10

two Runoob 12

three Wiki 13

从以上输出结果可以知道, DataFrame数据类型一个表格,包含rows(行)和columns(列)。

(4)列表嵌套字典创建DataFrame对象

列表嵌套字典可以作为输入数据传递给DataFrame构造函数。默认情况下,字典的键被用作列名。

import pandas as pd

# 列表嵌套字典

data1 = [{ 'a': 1, 'b': 2}, { 'a': 5, 'b': 10, 'c': 20}]

# 字典嵌套列表

data2 = { 'a':[1, 5], 'b':[2, 10], 'c':[15, 20]}

df1 = pd.DataFrame(data1)

print(df1)

df2 = pd.DataFrame(data2)

print(df2)

# 添加行标签索引

df3 = pd.DataFrame(data1,index = ['one','two'])

print(df3)

# 行标签索引

# 注意:因为'abc'在字典键中不存在,所以对应值为NaN

df4 = pd.DataFrame(data1,index = ['one','two'],columns = ['a','abc'])

print(df4)

# 输出结果,没有对应的部分数据为NaN。

a b c

0 1 2 NaN

1 5 10 20.0

a b c

0 1 2 15

1 5 10 20

a b c

one 1 2 NaN

two 5 10 20.0

a abc

one 1 NaN

two 5 NaN

(5)Series创建DataFrame对象

可以传递一个字典形式的Series,从而创建一个DataFrame对象,其输出结果的行索引是所有index的合集。

import pandas as pd

d = { 'one' : pd.Series([1, 2, 3], index = ['a', 'b', 'c']),

'two' : pd.Series([1, 2, 3, 4], index = ['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)

print(df)

# 输出结果,对于one列而言,此处虽然显示了行索引'd',但由于没有与其对应的值,所以它的值为NaN

one two

a 1.0 1

b 2.0 2

c 3.0 3

d NaN 4

👀列索引操作DF对象

DataFrame可以使用列索(columns index)引来完成数据的选取、添加和删除操作。

(1)列索引选取数据列

import pandas as pd

data = {

"calories": [420, 380, 390],

"duration": [50, 40, 45]

}

# 数据载入到DataFrame对象

df = pd.DataFrame(data, index = ['a', 'b', 'c'])

print(df)

# 返回第一列

print(df['calories'])

# 输出结果

calories duration

a 420 50

b 380 40

c 390 45

a 420

b 380

c 390

Name: calories, dtype: int64

(2)列索引添加数据列

使用columns列索引表标签可以实现添加新的数据列。

import pandas as pd

data = {

"calories": [420, 380, 390],

"duration": [50, 40, 45]

}

# 数据载入到DataFrame对象

df = pd.DataFrame(data, index = ['a', 'b', 'c'])

print(df)

# 返回第一列

print("*"*20)

# 使用df['列']=值,插入新的数据列

df['height'] = pd.Series([160,170,180], index = ['a', 'b', 'c'])

print(df)

print("*"*20)

# 将已经存在的数据列做相加运算

df['sums'] = df['calories'] + df['duration']

print(df)

# 输出结果

calories duration

a 420 50

b 380 40

c 390 45

********************

calories duration height

a 420 50 160

b 380 40 170

c 390 45 180

********************

calories duration height sums

a 420 50 160 470

b 380 40 170 420

c 390 45 180 435

我们初次使用了DataFrame的算术运算,这和NumPy非常相似。除了使用df[]=value的方式外,您还可以使用insert()方法插入新的列.

import pandas as pd

info = [['Jack',18],['Helen',19],['John',17]]

df = pd.DataFrame(info,columns = ['name','age'])

print(df)

# 注意是column参数

# 数值1代表插入到columns列表的索引位置

df.insert(1,column = 'score',value = [91,90,75])

print(df)

# 输出结果

name age

0 Jack 18

1 Helen 19

2 John 17

name score age

0 Jack 91 18

1 Helen 90 19

2 John 75 17

(3)列索引删除数据列

通过delpop()都能够删除DataFrame中的数据列。示例如下:

import pandas as pd

d = { 'one': pd.Series([1, 2, 3], index = ['a', 'b', 'c']),

'two': pd.Series([1, 2, 3, 4], index = ['a', 'b', 'c', 'd']),

'three': pd.Series([10,20,30], index = ['a','b','c'])}

df = pd.DataFrame(d)

print(df)

print("*"*20)

# 使用del删除

del df['one']

print(df)

print("*"*20)

# 使用pop方法删除

df.pop('two')

print(df)

# 输出结果

one two three

a 1.0 1 10.0

b 2.0 2 20.0

c 3.0 3 30.0

d NaN 4 NaN

********************

two three

a 1 10.0

b 2 20.0

c 3 30.0

d 4 NaN

********************

three

a 10.0

b 20.0

c 30.0

d NaN

👀行索引操作DF对象

Pandas可以使用loc函数返回指定行的数据,如果没有设置索引,第一行索引为0,第二行索引为1,以此类推。

(1)标签索引选取

通过将行标签传递给loc函数,来选取数据。

loc允许接两个参数分别是行和列,参数之间需要使用“逗号”隔开,但该函数只能接收标签索引

import pandas as pd

data = {

"calories": [420, 380, 390],

"duration": [50, 40, 45]

}

# 数据载入到 DataFrame 对象

df = pd.DataFrame(data, index = ['a', 'b', 'c'])

print(df)

print('*'*20)

print(df.loc['a'])

# 输出结果

calories duration

a 420 50

b 380 40

c 390 45

********************

calories 420

duration 50

Name: a, dtype: int64

(2)整数索引选取

通过将数据行所在的索引位置传递给iloc函数,也可以实现数据行选取。

iloc允许接受两个参数分别是行和列,参数之间使用“逗号”隔开,但该函数只能接收整数索引

import pandas as pd

data = {

"calories": [420, 380, 390],

"duration": [50, 40, 45]

}

# 数据载入到 DataFrame 对象

df = pd.DataFrame(data, index = ['a', 'b', 'c'])

print(df)

print('*'*20)

# 返回第一行,返回结果其实就是一个Pandas Series数据。

print(df.iloc[0])

print('*'*20)

# 返回第二行,返回结果其实就是一个Pandas Series数据。

print(df.iloc[1])

print('*'*20)

# 也可以返回多行数据,使用[[ ... ]] 格式,... 为各行的索引,以逗号隔开:

# 返回第一行和第二行,返回结果其实就是一个Pandas DataFrame数据。

print(df.iloc[[0, 1]])

# 输出结果

calories duration

a 420 50

b 380 40

c 390 45

********************

calories 420

duration 50

Name: a, dtype: int64

********************

calories 380

duration 40

Name: b, dtype: int64

********************

calories duration

a 420 50

b 380 40

(3)切片操作多行数据

通过使用切片的方式同时选取多行。

import pandas as pd

data = {

"calories": [420, 380, 390],

"duration": [50, 40, 45]

}

# 数据载入到 DataFrame 对象

df = pd.DataFrame(data, index = ['a', 'b', 'c'])

print(df)

print('*'*20)

# 左闭右开

print(df[1:3])

# 输出结果

calories duration

a 420 50

b 380 40

c 390 45

********************

calories duration

b 380 40

c 390 45

(4)添加数据行

使用append()函数,可以将新的数据行添加到DataFrame中,该函数会在行末追加数据行。

import pandas as pd

df = pd.DataFrame([[1, 2], [3, 4]], index = ['one','two'], columns = ['a','b'])

df2 = pd.DataFrame([[5, 6], [7, 8]], index = ['one','two'], columns = ['a','b'])

# 在行末追加新数据行

df = df.append(df2)

print(df)

# 输出结果

a b

one 1 2

two 3 4

one 5 6

two 7 8

(5)删除数据行

使用行索引标签,从DataFrame中删除某一行数据。如果索引标签存在重复,那么它们将被一起删除。

import pandas as pd

df = pd.DataFrame([[1, 2], [3, 4]], index = ['one','two'], columns = ['a','b'])

df2 = pd.DataFrame([[5, 6], [7, 8]], index = ['one','two'], columns = ['a','b'])

# 在行末追加新数据行

df = df.append(df2)

print(df)

print('*'*20)

# 注意此处调用了drop()方法,drop('one')同时删除了两行数据

df1 = df.drop('one')

print(df1)

# 输出结果

a b

one 1 2

two 3 4

one 5 6

two 7 8

********************

a b

two 3 4

two 7 8

👀DF对象属性和方法

DataFrame的属性和方法,与Series相差无几。

名称 属性方法描述
T 行和列转置
axes 返回一个仅以行轴标签和列轴标签为成员的列表
dtypes 返回每列数据的数据类型
empty DataFrame中没有数据或者任意坐标轴的长度为0,则返回True
ndim 轴的数量,也指数组的维数。
shape 返回一个元组,表示了DataFrame维度
size DataFrame中的元素数量
values 使用numpy数组表示DataFrame中的元素值
head() 返回前n行数据
tail() 返回后n行数据
shift() 将行或列移动指定的步幅长度

import pandas as pd

import numpy as np

d = { 'Name':pd.Series(['小汤','小王',"小明",'小红','小小','小微','小黄']),

'years':pd.Series([2005,2006,2015,2008,2003,2009,2003]),

'height':pd.Series([180,175,178,179,176,170,173])}

# 构建DataFrame

df = pd.DataFrame(d)

# 输出

print(df)

print('*'*20)

# T(Transpose)转置,返回DataFrame的转置,也就是把行和列进行交换

print(df.T)

print('*'*20)

# 返回一个行标签、列标签组成的列表

print(df.axes)

print('*'*20)

# 返回每一列的数据类型

print(df.dtypes)

print('*'*20)

# 返回一个布尔值,判断输出的数据对象是否为空,若为True表示对象为空

print(df.empty)

print('*'*20)

# 返回数据对象的维数。DataFrame是一个二维数据结构

print(df.ndim)

print('*'*20)

# 返回一个代表DataFrame维度的元组。返回值元组(a,b),其中a表示行数,b表示列数

print(df.shape)

print('*'*20)

# 返回DataFrame中的元素数量

print(df.size)

print('*'*20)

# 以ndarray数组的形式返回DataFrame中的数据

print(df.values)

print('*'*20)

# 输出结果

Name years height

0 小汤 2005 180

1 小王 2006 175

2 小明 2015 178

3 小红 2008 179

4 小小 2003 176

5 小微 2009 170

6 小黄 2003 173

********************

0 1 2 3 4 5 6

Name 小汤 小王 小明 小红 小小 小微 小黄

years 2005 2006 2015 2008 2003 2009 2003

height 180 175 178 179 176 170 173

********************

[RangeIndex(start=0, stop=7, step=1), Index(['Name', 'years', 'height'], dtype='object')]code>

********************

Name object

years int64

height int64

dtype: object

********************

False

********************

2

********************

(7, 3)

********************

21

********************

[['小汤' 2005 180]

['小王' 2006 175]

['小明' 2015 178]

['小红' 2008 179]

['小小' 2003 176]

['小微' 2009 170]

['小黄' 2003 173]]

********************

head()&tail()查看数据。如果想要查看DataFrame的一部分数据,可以使用head()或者tail()方法。head()返回前n行数据,默认显示前5行数据。tail()返回后n行数据。

import pandas as pd

import numpy as np

d = { 'Name':pd.Series(['小汤','小王',"小明",'小红','小小','小微','小黄']),

'years':pd.Series([2005,2006,2015,2008,2003,2009,2003]),

'height':pd.Series([180,175,178,179,176,170,173])}

# 构建DataFrame

df = pd.DataFrame(d)

# 输出

print(df)

print('*'*20)

# 获取前3行数据

print(df.head(3))

print('*'*20)

# 获取后2行数据

print(df.tail(2))

# 输出结果

Name years height

0 小汤 2005 180

1 小王 2006 175

2 小明 2015 178

3 小红 2008 179

4 小小 2003 176

5 小微 2009 170

6 小黄 2003 173

********************

Name years height

0 小汤 2005 180

1 小王 2006 175

2 小明 2015 178

********************

Name years height

5 小微 2009 170

6 小黄 2003 173

shift()移动行或列。如果您想要移动DataFrame中的某一行/列,可以使用shift()函数实现。它提供了一个periods参数,该参数表示在特定的轴上移动指定的步幅。

DataFrame.shift(periods=1, freq=None, axis=0)

参数说明:

peroids类型为int,表示移动的幅度,可以是正数,也可以是负数,默认值为1。

freq日期偏移量,默认值为None,适用于时间序。取值为符合时间规则的字符串。

axis如果是0或者"index"表示上下移动,如果是1或者"columns"则会左右移动。

fill_value该参数用来填充缺失值。

import pandas as pd

import numpy as np

d = { 'Name':pd.Series(['小汤','小王',"小明",'小红','小小','小微','小黄']),

'years':pd.Series([2005,2006,2015,2008,2003,2009,2003]),

'height':pd.Series([180,175,178,179,176,170,173])}

# 构建DataFrame

df = pd.DataFrame(d)

# 输出

print(df)

print('*'*20)

# 移动幅度为3

print(df.shift(periods=3))

print('*'*20)

# 使用fill_value参数填充DataFrame中的缺失值

print(df.shift(periods=3,fill_value=52))

print('*'*20)

print(df.shift(periods=3,axis=1,fill_value=52))

# 输出结果

Name years height

0 小汤 2005 180

1 小王 2006 175

2 小明 2015 178

3 小红 2008 179

4 小小 2003 176

5 小微 2009 170

6 小黄 2003 173

********************

Name years height

0 NaN NaN NaN

1 NaN NaN NaN

2 NaN NaN NaN

3 小汤 2005.0 180.0

4 小王 2006.0 175.0

5 小明 2015.0 178.0

6 小红 2008.0 179.0

********************

Name years height

0 52 52 52

1 52 52 52

2 52 52 52

3 小汤 2005 180

4 小王 2006 175

5 小明 2015 178

6 小红 2008 179

********************

Name years height

0 52 52 52

1 52 52 52

2 52 52 52

3 52 52 52

4 52 52 52

5 52 52 52

6 52 52 52

⛄Pandas函数操作

👀Panel结构(了解)

Panel是一个用来承载数据的三维数据结构,它有三个轴,分别是items(0轴),major_axis(1轴),而 minor_axis(2轴)。这三个轴为描述、操作Panel提供了支持,其作用介绍如下:

items:axis =0,Panel 中的每个items都对应一个DataFramemajor_axis:axis=1,用来描述每个DataFrame的行索引。minor_axis:axis=2,用来描述每个DataFrame的列索引。

pandas.Panel(data, items, major_axis, minor_axis, dtype, copy)

参数说明:

data输入数据,可以是 ndarray,Series,列表,字典,或者 DataFrame。

itemsaxis=0

major_axisaxis=1

minor_axisaxis=2

dtype每一列的数据类型。

copy默认为 False,表示是否复制数据。

Pandas 0.25版本后, Panel结构已经被废弃。

👀描述性统计函数

函数名称 描述说明
count() 统计某个非空值的数量
sum() 求和
mean() 求均值
median() 求中位数
mode() 求众数
std() 求标准差
min() 求最小值
max() 求最大值
abs() 求绝对值
prod() 求所有数值的乘积
cumsum() 计算累计和,axis=0,按照行累加;axis=1,按照列累加
cumprod() 计算累计积,axis=0,按照行累积;axis=1,按照列累积
corr() 计算数列或变量之间的相关系数,取值-1到1,值越大表示关联性越强
describe() 显示与DataFrame数据列相关的统计信息摘要

DataFrame中,使用聚合类方法时需要指定轴(axis)参数。下面介绍两种传参方式:

对行操作,默认使用axis=0或者使用 “index”;对列操作,默认使用axis=1或者使用 “columns”。axis=0表示按垂直方向进行计算,而axis=1则表示按水平方向。

describe()函数输出了平均值、stdIQR值(四分位距)等一系列统计信息。通过describe()提供的include能够筛选字符列或者数字列的摘要信息。include相关参数值说明如下:

object: 表示对字符列进行统计信息描述;number:表示对数字列进行统计信息描述;all:汇总所有列的统计信息。

import pandas as pd

import numpy as np

d = { 'Name':pd.Series(['小汤','小王',"小明",'小红','小小','小微','小黄']),

'years':pd.Series([2005,2006,2015,2008,2003,2009,2003]),

'height':pd.Series([180,175,178,179,176,170,173])}

# 构建DataFrame

df = pd.DataFrame(d)

# 输出

print(df)

print('*'*20)

# 求出数据的所有描述信息

print(df.describe())

print('*'*20)

print(df.describe(include=["object"]))

print('*'*20)

print(df.describe(include="all"))code>

# 输出结果

Name years height

0 小汤 2005 180

1 小王 2006 175

2 小明 2015 178

3 小红 2008 179

4 小小 2003 176

5 小微 2009 170

6 小黄 2003 173

********************

years height

count 7.000000 7.000000

mean 2007.000000 175.857143

std 4.203173 3.532165

min 2003.000000 170.000000

25% 2004.000000 174.000000

50% 2006.000000 176.000000

75% 2008.500000 178.500000

max 2015.000000 180.000000

********************

Name

count 7

unique 7

top 小汤

freq 1

********************

Name years height

count 7 7.000000 7.000000

unique 7 NaN NaN

top 小汤 NaN NaN

freq 1 NaN NaN

mean NaN 2007.000000 175.857143

std NaN 4.203173 3.532165

min NaN 2003.000000 170.000000

25% NaN 2004.000000 174.000000

50% NaN 2006.000000 176.000000

75% NaN 2008.500000 178.500000

max NaN 2015.000000 180.000000

👀自定义函数

如果想要应用自定义的函数,或者把其他库中的函数应用到Pandas对象中,有以下三种方法:

操作整个DataFrame的函数:pipe()操作行或者列的函数:apply()操作单一元素的函数:applymap()

(1)操作整个数据表

通过给pipe()函数传递一个自定义函数和适当数量的参数值,从而操作DataFrme中的所有元素。下面示例,实现了数据表中的元素值依次加 6。

import pandas as pd

import numpy as np

# 自定义函数

def addsum(a1,a2):

return a1 + a2

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

# 相加前

print(df)

# 相加后

print(df.pipe(addsum,6))

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

c1 c2 c3

0 126 136 156

1 96 106 116

2 66 76 86

(2)操作行或列

如果要操作DataFrame的某一行或者某一列,可以使用apply()方法,该方法与描述性统计方法类似,都有可选参数axis,并且默认按列操作。示例如下:

import pandas as pd

import numpy as np

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

# 默认按列操作,计算每一列均值

print(df.apply(np.mean))

print('*'*20)

# 传递轴参axis=1,表示逐行进行操作

print(df.apply(np.mean,axis=1))

print('*'*20)

# 求每一列中,最大值与最小值之差

print(df.apply(lambda x: x.max() - x.min()))

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

c1 90.000000

c2 100.000000

c3 113.333333

dtype: float64

********************

0 133.333333

1 100.000000

2 70.000000

dtype: float64

********************

c1 60

c2 60

c3 70

dtype: int64

(3)操作单一元素

DataFrame数据表结构的applymap()Series系列结构的map()类似,它们都可以接受一个Python函数,并返回相应的值。

import pandas as pd

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

# 自定义函数lambda函数

print(df['c1'].map(lambda x:x*10))

print('*'*20)

# 使用了applymap()函数

print(df.applymap(lambda x:x*10))

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

0 1200

1 900

2 600

Name: c1, dtype: int64

********************

c1 c2 c3

0 1200 1300 1500

1 900 1000 1100

2 600 700 800

👀reindex重置索引

重置索引(reindex)可以更改原DataFrame的行标签或列标签,并使更改后的行、列标签与DataFrame中的数据逐一匹配。通过重置索引操作,您可以完成对现有数据的重新排序。如果重置的索引标签在原DataFrame中不存在,那么该标签对应的元素值将全部填充为NaN

(1)重置行列标签

import pandas as pd

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

# 重置行、列索引标签

df_reindexed = df.reindex(index=[0,1], columns=['c1', 'c3'])

print(df_reindexed)

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

c1 c3

0 120 150

1 90 110

现有a、b两个DataFrame对象,如果想让a的行索引与b相同,您可以使用reindex_like() 方法。示例如下:

import pandas as pd

import numpy as np

a = pd.DataFrame(np.random.randn(10,3),columns=['col1','col2','col3'])

b = pd.DataFrame(np.random.randn(7,3),columns=['col1','col2','col3'])

# a会按照b的形式重建行索引。需要特别注意的是,a与b的列索引标签必须相同。

a= a.reindex_like(b)

print(a)

# 输出结果

col1 col2 col3

0 0.669617 0.010243 -0.091776

1 -0.333395 -1.521432 0.292087

2 -0.174709 -0.623413 1.291384

3 1.033132 -0.383137 1.280788

4 1.052466 -1.326848 -1.390581

5 1.828058 0.422678 -0.734622

6 0.988210 -1.047092 -1.959839

(2)填充元素值

reindex_like()提供了一个可选的参数method,使用它来填充相应的元素值,参数值介绍如下:

pad/ffill:向前填充值;bfill/backfill:向后填充值;nearest:从距离最近的索引值开始填充。

reindex_like()还提供了一个额外参数limit,该参数用来控制填充的最大行数。示例如下:

import pandas as pd

import numpy as np

df1 = pd.DataFrame(np.random.randn(6,3),columns=['col1','col2','col3'])

df2 = pd.DataFrame(np.random.randn(2,3),columns=['col1','col2','col3'])

# 使df2和df1行标签相同

print(df2.reindex_like(df1))

print('*'*20)

# 向前填充

print(df2.reindex_like(df1,method='ffill'))code>

print('*'*20)

# 向后填充

print(df2.reindex_like(df1,method='backfill'))code>

print('*'*20)

# limit限制填充行数

print(df2.reindex_like(df1,method='ffill',limit=2))code>

# 输出结果

col1 col2 col3

0 0.552991 1.230408 0.403586

1 -0.135228 1.065911 -0.624843

2 NaN NaN NaN

3 NaN NaN NaN

4 NaN NaN NaN

5 NaN NaN NaN

********************

col1 col2 col3

0 0.552991 1.230408 0.403586

1 -0.135228 1.065911 -0.624843

2 -0.135228 1.065911 -0.624843

3 -0.135228 1.065911 -0.624843

4 -0.135228 1.065911 -0.624843

5 -0.135228 1.065911 -0.624843

********************

col1 col2 col3

0 0.552991 1.230408 0.403586

1 -0.135228 1.065911 -0.624843

2 NaN NaN NaN

3 NaN NaN NaN

4 NaN NaN NaN

5 NaN NaN NaN

********************

col1 col2 col3

0 0.552991 1.230408 0.403586

1 -0.135228 1.065911 -0.624843

2 -0.135228 1.065911 -0.624843

3 -0.135228 1.065911 -0.624843

4 NaN NaN NaN

5 NaN NaN NaN

(3)重命名标签

rename()方法允许您使用某些映射(dictSeries)或任意函数来对行、列标签重新命名,示例如下:

import pandas as pd

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

# 对行和列重新命名

print(df.rename(columns={ 'c1':'cc1','c2':'cc2'},index = { 0:'one',1:'two',2:'three'}))

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

cc1 cc2 c3

one 120 130 150

two 90 100 110

three 60 70 80

rename()方法提供了一个inplace参数,默认值为False,表示拷贝一份原数据,并在复制后的数据上做重命名操作。若inplace=True则表示在原数据的基础上重命名。

👀iteration遍历操作

Pandas是如何遍历SeriesDataFrame结构呢?对于Series而言,您可以把它当做一维数组进行遍历操作;而像DataFrame这种二维数据表结构,则类似于遍历Python字典。

Pandas中同样也是使用for循环进行遍历。通过for遍历后,Series可直接获取相应的value,而DataFrame则会获取列标签。示例如下:

import pandas as pd

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

for col in df:

print (col)

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

c1

c2

c3

如果想要遍历DataFrame的每一行,我们下列函数:

iteritems():以键值对 (key,value) 的形式遍历;iterrows():以 (row_index,row) 的形式遍历行;itertuples():使用已命名元组的方式对行遍历。

iteritems()以键值对的形式遍历DataFrame对象,以列标签为键,以对应列的元素为值。

import pandas as pd

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

for key,value in df.iteritems():

print(key)

print(value)

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

c1

0 120

1 90

2 60

Name: c1, dtype: int64

c2

0 130

1 100

2 70

Name: c2, dtype: int64

c3

0 150

1 110

2 80

Name: c3, dtype: int64

iterrows()方法按行遍历,返回一个迭代器,以行索引标签为键,以每一行数据为值。

import pandas as pd

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

# iterrows()遍历行,其中0,1,2是行索引而c1,c2,c3是列索引。

for row_index,value in df.iterrows():

print(row_index)

print(value)

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

0

c1 120

c2 130

c3 150

Name: 0, dtype: int64

1

c1 90

c2 100

c3 110

Name: 1, dtype: int64

2

c1 60

c2 70

c3 80

Name: 2, dtype: int64

itertuples()同样将返回一个迭代器,该方法会把DataFrame每一行生成一个元组,示例如下:

import pandas as pd

# 操作DataFrame

df = pd.DataFrame([[120,130,150],[90,100,110],[60,70,80]],columns=['c1','c2','c3'])

print(df)

print('*'*20)

for row in df.itertuples():

print(row)

# 输出结果

c1 c2 c3

0 120 130 150

1 90 100 110

2 60 70 80

********************

Pandas(Index=0, c1=120, c2=130, c3=150)

Pandas(Index=1, c1=90, c2=100, c3=110)

Pandas(Index=2, c1=60, c2=70, c3=80)

迭代器返回的是原对象的副本,如果在迭代过程中修改元素值,不会影响原对象。

👀排序和去重

👁排序sorting

Pandas提供了两种排序方法,分别是按标签排序和按数值排序。

(1)按行标签排序

使用sort_index()方法对行标签排序,指定轴参数(axis)或者排序顺序。或者可以对DataFrame进行排序。默认情况下,按照行标签序排序。通过将布尔值传递给ascending参数,可以控制排序的顺序(行号顺序)。

import pandas as pd

import numpy as np

# 行标签乱序排列,列标签乱序排列

unsorted_df = pd.DataFrame(np.random.randn(6,2),index=[1,4,2,3,5,0],columns=['col2','col1'])

print(unsorted_df)

print('*'*20)

sorted_df1 = unsorted_df.sort_index()

print(sorted_df1)

print('*'*20)

sorted_df2 = unsorted_df.sort_index(ascending=False)

print(sorted_df2)

# 输出结果

col2 col1

1 -0.458463 0.422606

4 0.809682 2.489952

2 1.609935 0.096181

3 1.087255 1.215676

5 0.436520 0.389565

0 0.536720 0.820746

********************

col2 col1

0 0.536720 0.820746

1 -0.458463 0.422606

2 1.609935 0.096181

3 1.087255 1.215676

4 0.809682 2.489952

5 0.436520 0.389565

********************

col2 col1

5 0.436520 0.389565

4 0.809682 2.489952

3 1.087255 1.215676

2 1.609935 0.096181

1 -0.458463 0.422606

0 0.536720 0.820746

(2)按列标签排序

通过给axis轴参数传递0或1,可以对列标签进行排序。默认情况下,axis=0表示按行排序;而axis=1则表示按列排序。

import pandas as pd

import numpy as np

# 行标签乱序排列,列标签乱序排列

unsorted_df = pd.DataFrame(np.random.randn(6,2),index=[1,4,2,3,5,0],columns=['col2','col1'])

print(unsorted_df)

print('*'*20)

sorted_df1 = unsorted_df.sort_index(axis=1)

print(sorted_df1)

# 输出结果

col2 col1

1 0.891755 1.006258

4 0.232999 0.549146

2 0.158894 0.246825

3 0.653124 -1.695749

5 -0.774252 -0.525881

0 0.082147 0.384929

********************

col1 col2

1 1.006258 0.891755

4 0.549146 0.232999

2 0.246825 0.158894

3 -1.695749 0.653124

5 -0.525881 -0.774252

0 0.384929 0.082147

(3)按值排序

与标签排序类似,sort_values()表示按值排序。它接受一个by参数,该参数值是要排序数列的DataFrame列名。示例如下:

import pandas as pd

# 行标签乱序排列,列标签乱序排列

unsorted_df = pd.DataFrame({ 'col1':[2,1,1,1],'col2':[1,3,2,4]})

print(unsorted_df)

print('*'*20)

sorted_df1 = unsorted_df.sort_values(by='col1')code>

print(sorted_df1)

print('*'*20)

# 注意:当对col1列排序时,相应的col2列的元素值和行索引也会随col1一起改变。by参数可以接受一个列表参数值

sorted_df2 = unsorted_df.sort_values(by=['col1','col2'])

print(sorted_df2)

# 输出结果

col1 col2

0 2 1

1 1 3

2 1 2

3 1 4

********************

col1 col2

1 1 3

2 1 2

3 1 4

0 2 1

********************

col1 col2

2 1 2

1 1 3

3 1 4

0 2 1

(4)排序算法

sort_values()提供了参数kind用来指定排序算法。这里有三种排序算法:

mergesortheapsortquicksort

默认为quicksort(快速排序) ,其中Mergesort归并排序是最稳定的算法。

import pandas as pd

# 行标签乱序排列,列标签乱序排列

unsorted_df = pd.DataFrame({ 'col1':[2,1,1,1],'col2':[1,3,2,4]})

print(unsorted_df)

print('*'*20)

sorted_df1 = unsorted_df.sort_values(by='col1',kind='mergesort')code>

print(sorted_df1)

# 输出结果

col1 col2

0 2 1

1 1 3

2 1 2

3 1 4

********************

col1 col2

1 1 3

2 1 2

3 1 4

0 2 1

👁去重drop_duplicates()

“去重”通过字面意思不难理解,就是删除重复的数据。在一个数据集中,找出重复的数据删并将其删除,最终只保存一个唯一存在的数据项,这就是数据去重的整个过程。

Panda DataFrame对象提供了一个数据去重的函数drop_duplicates()

df.drop_duplicates(subset=['A','B','C'],keep='first',inplace=True)code>

参数说明如下:

subset:表示要进去重的列名,默认为None。

keep:有三个可选参数,分别是first、last、False,默认为first,表示只保留第一次出现的重复项,删除其余重复项,last表示只保留最后一次出现的重复项,False则表示删除所有重复项。

inplace:布尔值参数,默认为False表示删除重复项后返回一个副本,若为Ture则表示直接在原数据上删除重复项。

删除重复项后,行标签使用的数字是原来的,并没有从0重新开始,那么我们应该怎么从0重置索引呢?Pandas提供的reset_index()函数会直接使用重置后的索引。

import pandas as pd

data = { 'col1':[1,0,1,1],'col2':[0,2,5,0],'col3':[4,0,4,4],'col4':[1,0,1,1]}

df = pd.DataFrame(data)

print(df)

print('*'*20)

# 默认保留第一次出现的重复项,默认为first

print(df.drop_duplicates())

print('*'*20)

# keep=False删除所有重复项

df1 = df.drop_duplicates(keep=False)

print(df1)

print('*'*20)

# 重置索引,从0重新开始

print(df1.reset_index(drop=True))

print('*'*20)

# 指定多列同时去重

print(df.drop_duplicates(['col3','col4'],keep='last'))code>

# 输出结果

col1 col2 col3 col4

0 1 0 4 1

1 0 2 0 0

2 1 5 4 1

3 1 0 4 1

********************

col1 col2 col3 col4

0 1 0 4 1

1 0 2 0 0

2 1 5 4 1

********************

col1 col2 col3 col4

1 0 2 0 0

2 1 5 4 1

********************

col1 col2 col3 col4

0 0 2 0 0

1 1 5 4 1

********************

col1 col2 col3 col4

1 0 2 0 0

3 1 0 4 1

👀字符串处理

Pandas提供了一系列的字符串函数,因此能够很方便地对字符串进行处理。

函数名称 函数功能和描述
lower() 将的字符串转换为小写
upper() 将的字符串转换为大写
len() 得出字符串的长度
strip() 去除字符串两边的空格(包含换行符)
split() 用指定的分割符分割字符串
cat(sep="")code> 用给定的分隔符连接字符串元素
get_dummies() 返回一个带有独热编码值的DataFrame结构
contains(pattern) 如果子字符串包含在元素中,则为每个元素返回一个布尔值True,否则为False
replace(a,b) 将值a替换为值b
count(pattern) 返回每个字符串元素出现的次数
startswith(pattern) 如果Series中的元素以指定的字符串开头,则返回True
endswith(pattern) 如果Series中的元素以指定的字符串结尾,则返回True
findall(pattern) 以列表的形式返出现的字符串
swapcase() 交换大小写
islower() 返回布尔值,检查Series中组成每个字符串的所有字符是否都为小写
issupper() 返回布尔值,检查Series中组成每个字符串的所有字符是否都为大写
isnumeric() 返回布尔值,检查Series中组成每个字符串的所有字符是否都为数字
repeat(value) 以指定的次数重复每个元素
find(pattern) 返回字符串第一次出现的索引位置

注意:上述所有字符串函数全部适用于DataFrame对象,同时也可以与Python内置的字符串函数一起使用,这些函数在处理Series/DataFrame对象的时候会自动忽略缺失值数据(NaN)。

import pandas as pd

import numpy as np

s = pd.Series(['C ', ' Python', 'java', 'go', np.nan, '1125 ','javascript'])

print(s.str.lower)

print('*'*20)

print(s.str.len())

print('*'*20)

print(s.str.strip())

print('*'*20)

print(s.str.split(" "))

print('*'*20)

print(s.str.cat(sep="_"))code>

print('*'*20)

print(s.str.get_dummies())

print('*'*20)

print(s.str.contains(" "))

print('*'*20)

print(s.str.repeat(3))

print('*'*20)

print(s.str.startswith("j"))

print('*'*20)

# 如果返回-1表示该字符串中没有出现指定的字符

print(s.str.find("j"))

print('*'*20)

print(s.str.swapcase())

print('*'*20)

print(s.str.isnumeric())

# 输出结果

0 c

1 python

2 java

3 go

4 NaN

5 1125

6 javascript

dtype: object

********************

0 2.0

1 7.0

2 4.0

3 2.0

4 NaN

5 5.0

6 10.0

dtype: float64

********************

0 C

1 Python

2 java

3 go

4 NaN

5 1125

6 javascript

dtype: object

********************

0 [C, ]

1 [, Python]

2 [java]

3 [go]

4 NaN

5 [1125, ]

6 [javascript]

dtype: object

********************

C _ Python_java_go_1125 _javascript

********************

Python 1125 C go java javascript

0 0 0 1 0 0 0

1 1 0 0 0 0 0

2 0 0 0 0 1 0

3 0 0 0 1 0 0

4 0 0 0 0 0 0

5 0 1 0 0 0 0

6 0 0 0 0 0 1

********************

0 True

1 True

2 False

3 False

4 NaN

5 True

6 False

dtype: object

********************

0 C C C

1 Python Python Python

2 javajavajava

3 gogogo

4 NaN

5 1125 1125 1125

6 javascriptjavascriptjavascript

dtype: object

********************

0 False

1 False

2 True

3 False

4 NaN

5 False

6 True

dtype: object

********************

0 -1.0

1 -1.0

2 0.0

3 -1.0

4 NaN

5 -1.0

6 0.0

dtype: float64

********************

0 c

1 pYTHON

2 JAVA

3 GO

4 NaN

5 1125

6 JAVASCRIPT

dtype: object

********************

0 False

1 False

2 False

3 False

4 NaN

5 False

6 False

dtype: object

👀设置数据显示格式

在用Pandas做数据分析的过程中,总需要打印数据分析的结果,如果数据体量较大就会存在输出内容不全(部分内容省略)或者换行错误等问题。Pandas为了解决上述问题,允许你对数据显示格式进行设置。下面列出了五个用来设置显示格式的函数,分别是:

函数名称 说明
get_option() 获取解释器的默认参数值
set_option() 更改解释器的默认参数值
reset_option() 解释器的参数重置为默认值
describe_option() 输出参数的描述信息
option_context() 临时设置解释器参数,当退出使用的语句块时,恢复为默认值

上述函数常用的参数项:

参数 说明
display.max_rows 最大显示行数,超过该值用省略号代替,为None时显示所有行
display.max_columns 最大显示列数,超过该值用省略号代替,为None时显示所有列
display.expand_frame_repr 输出数据宽度超过设置宽度时,表示是否对其要折叠,False不折叠,True要折叠
display.max_colwidth 单列数据宽度,以字符个数计算,超过时用省略号表示
display.precision 设置输出数据的小数点位数
display.width 数据显示区域的宽度,以总字符数计算
display.show_dimensions 当数据量大需要以truncate(带引号的省略方式)显示时,该参数表示是否在最后显示数据的维数,默认True显示,False不显示。

👀loc和iloc用法详解

在数据分析过程中,很多时候需要从数据表中提取出相应的数据,而这么做的前提是需要先“索引”出这一部分数据。虽然通过Python提供的索引操作符"[]"和属性操作符"."可以访问Series或者DataFrame中的数据,但这种方式只适应与少量的数据,为了解决这一问题,Pandas提供了两种类型的索引方式来实现数据的访问。

方法名称 说明
.loc[] 基于标签索引选取数据
.iloc[] 基于整数索引选取数据

df.loc[]只能使用标签索引,不能使用整数索引。当通过标签索引的切片方式来筛选数据时,它的取值前闭后闭,也就是只包括边界值标签(开始和结束)。

.loc[]具有多种访问方法,如下所示:

一个标量标签标签列表切片对象布尔数组

loc[]接受两个参数,并以','分隔。第一个位置表示行,第二个位置表示列。

import pandas as pd

data = {

"name": ['Tom', 'Rose', 'Mike', 'Twg'],

"calories": [420, 380, 390, 500],

"duration": [50, 40, 45, 60]

}

# 数据载入到 DataFrame 对象

df = pd.DataFrame(data, index = ['a', 'b', 'c', 'd'])

print(df)

print('*'*20)

# 对行操作,等同于df.loc['a':'b']

print(df.loc['a':'b',:])

print('*'*20)

# 对列操作

print(df.loc[:,'name'])

print('*'*20)

# 对行、列操作

print(df.loc[['a','d'],['name','duration']])

print('*'*20)

# 布尔值操作

print(df.loc[:,'duration'] > 45)

# 输出结果

name calories duration

a Tom 420 50

b Rose 380 40

c Mike 390 45

d Twg 500 60

********************

name calories duration

a Tom 420 50

b Rose 380 40

********************

a Tom

b Rose

c Mike

d Twg

Name: name, dtype: object

********************

name duration

a Tom 50

d Twg 60

********************

a True

b False

c False

d True

Name: duration, dtype: bool

df.iloc[]只能使用整数索引,不能使用标签索引,通过整数索引切片选择数据时,前闭后开(不包含边界结束值)。同PythonNumPy一样,它们的索引都是从0开始。

.iloc[]提供了以下方式来选择数据:

整数索引整数列表数值范围

import pandas as pd

data = {

"name": ['Tom', 'Rose', 'Mike', 'Twg'],

"calories": [420, 380, 390, 500],

"duration": [50, 40, 45, 60]

}

# 数据载入到 DataFrame 对象

df = pd.DataFrame(data, index = ['a', 'b', 'c', 'd'])

print(df)

print('*'*20)

print(df.iloc[2:,:])

print('*'*20)

print(df.iloc[[0,2],[1,2]])

print('*'*20)

print(df.iloc[:,:2])

# 输出结果

name calories duration

a Tom 420 50

b Rose 380 40

c Mike 390 45

d Twg 500 60

********************

name calories duration

c Mike 390 45

d Twg 500 60

********************

calories duration

a 420 50

c 390 45

********************

name calories

a Tom 420

b Rose 380

c Mike 390

d Twg 500

👀日期时间操作

👁Pandas时间序列

顾名思义,时间序列(time series),就是由时间构成的序列,它指的是在一定时间内按照时间顺序测量的某个变量的取值序列,比如一天内的温度会随时间而发生变化,或者股票的价格会随着时间不断的波动,这里用到的一系列时间,就可以看做时间序列。时间序列包含三种应用场景,分别是:

特定的时刻(timestamp),也就是时间戳;固定的日期(period),比如某年某月某日;时间间隔(interval),每隔一段时间具有规律性;

在处理时间序列的过程中,我们一般会遇到两个问题,第一,如何创建时间序列;第二,如何更改已生成时间序列的频率。 Pandas为解决上述问题提供了一套简单、易用的方法。

# Python内置的datetime模块来获取当前时间,通过该模块提供的now()方法即可实现。

from datetime import datetime

# 数据类型为datetime

print(datetime.now())

# 输出结果

2023-03-19 17:42:39.528176

创建时间戳:TimeStamp(时间戳) 是时间序列中的最基本的数据类型,它将数值与时间点完美结合在一起。

创建时间间隔:通过date_range()方法可以创建某段连续的时间或者固定间隔的时间时间段。该函数提供了三个参数,分别是:start开始时间;end结束时间;freq时间频率,默认为 “D”(天)。

import pandas as pd

# 创建时间戳

print(pd.Timestamp('2023-03-16'))

# 可以将整型或浮点型表示的时间转换为时间戳。默认的单位是纳秒(时间戳单位)

print(pd.Timestamp(1687687255,unit='s'))code>

print('*'*20)

# 创建时间范围,freq表示时间频率,每30min变化一次

print(pd.date_range("9:00", "18:10", freq="30min").time)code>

# 修改为按小时

print(pd.date_range("9:00", "18:10", freq="H").time)code>

print('*'*20)

# 使用to_datetime()函数将series或list转换为日期对象,其中list会转换为DatetimeIndex

# 输出中,注意:NaT表示的不是时间 ,它等效于NaN

# 传入series,生成Datetimeindex

print(pd.to_datetime(pd.Series(['Jun 3, 2020','2020-12-10', None])))

# 传入list,生成Datetimeindex

print(pd.to_datetime(['Jun 30, 2020','2020-12-10', None]))

# 输出结果

2023-03-16 00:00:00

2023-06-25 10:00:55

********************

[datetime.time(9, 0) datetime.time(9, 30) datetime.time(10, 0)

datetime.time(10, 30) datetime.time(11, 0) datetime.time(11, 30)

datetime.time(12, 0) datetime.time(12, 30) datetime.time(13, 0)

datetime.time(13, 30) datetime.time(14, 0) datetime.time(14, 30)

datetime.time(15, 0) datetime.time(15, 30) datetime.time(16, 0)

datetime.time(16, 30) datetime.time(17, 0) datetime.time(17, 30)

datetime.time(18, 0)]

[datetime.time(9, 0) datetime.time(10, 0) datetime.time(11, 0)

datetime.time(12, 0) datetime.time(13, 0) datetime.time(14, 0)

datetime.time(15, 0) datetime.time(16, 0) datetime.time(17, 0)

datetime.time(18, 0)]

********************

0 2020-06-03

1 2020-12-10

2 NaT

dtype: datetime64[ns]

DatetimeIndex(['2020-06-30', '2020-12-10', 'NaT'], dtype='datetime64[ns]', freq=None)code>

频率和周期转换:Time Periods表示时间跨度,一段时间周期,它被定义在Pandas Periods类中,通过该类提供的方法可以实现将频率转换为周期。比如Periods()方法,可以将频率 “M”(月)转换为 Period(时间段)。使用asfreq()start参数,打印 “01” ,若使用end参数,则打印 “31”。对于常用的时间序列频率,Pandas为其规定了一些字符串别名,我们将这些别名称为“offset(偏移量)”。

别名 描述 别名 描述
B 工作日频率 BQS 工作季度开始频率
D 日历日频率 A 年终频率
W 每周频率 BA 工作年度结束频率
M 月末频率 BAS 工作年度开始频率
SM 半月结束频率 BH 营业时间频率
BM 工作月结束频率 H 小时频率
MS 月开始频率 T,min 每分钟频率
SMS 半月开始频率 S 每秒钟频率
BMS 工作月开始频率 L,ms 毫秒
Q 季末频率 U,us 微秒
BQ 工作季度结束频率 N 纳秒
QS 季度开始频率

周期计算:指的是对时间周期进行算术运算,所有的操作将在“频率”的基础上执行。

创建时间周期:可以使用period_range()方法来创建时间周期范围。

时间序列转换:如果想要把字符串日期转换为Period,首先需要将字符串转换为日期格式,然后再将日期转换为Period

import pandas as pd

# S表示秒

x = pd.Period('2014', freq='S')code>

print(x)

# 加1s的时间

print(x+1)

# 使用period_range()方法来创建时间周期范围

p = pd.period_range('2016','2018', freq='Y')code>

print(p)

# 输出结果

2014-01-01 00:00:00

2014-01-01 00:00:01

PeriodIndex(['2016', '2017', '2018'], dtype='period[A-DEC]', freq='A-DEC')code>

👁日期时间格式化

当进行数据分析时,我们会遇到很多带有日期、时间格式的数据集,在处理这些数据集时,可能会遇到日期格式不统一的问题,此时就需要对日期时间做统一的格式化处理。比如"Wednesday, June 6, 2020"可以写成"6/6/20",或者写成"06-06-2020"。

(1)日期格式化符号

在对时间进行格式化处理时,它们都有固定的表示格式,比如小时的格式化符号为%H ,分钟简写为%M ,秒简写为%S

符号 说明 符号 说明
%y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999)
%m 月份(01-12) %d 月内中的一天(0-31)
%H 24小时制小时数(0-23) %I 12小时制小时数(01-12)
%M 分钟数(00=59) %S 秒(00-59)
%a 本地英文缩写星期名称 %A 本地英文完整星期名称
%b 本地缩写英文的月份名称 %B 本地完整英文的月份名称
%w 星期(0-6),星期天为星期的开始 %W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示 %X 本地相应的时间表示
%Z 当前时区的名称 %U 一年中的星期数(00-53)星期天为星期的开始
%j 年内的一天(001-366) %c 本地相应的日期表示和时间表示

(2)日期格式化处理函数

Python内置的strptime()方法能够将字符串日期转换为datetime类型。

from datetime import datetime

# 将日期定义为字符串

date_str1 = 'Wednesday,July 18,2020'

date_str2 = '18/7/20'

date_str3 = '18-07-2020'

# 将日期转化为datetime对象

dmy_dt1 = datetime.strptime(date_str1, '%A,%B %d,%Y')

dmy_dt2 = datetime.strptime(date_str2, '%d/%m/%y')

dmy_dt3 = datetime.strptime(date_str3, '%d-%m-%Y')

# 处理为相同格式,并打印输出

print(dmy_dt1)

print(dmy_dt2)

print(dmy_dt3)

# 输出结果

2020-07-18 00:00:00

2020-07-18 00:00:00

2020-07-18 00:00:00

除了使用Python内置的strptime()方法外,你还可以使用Pandas模块的pd.to_datetime()pd.DatetimeIndex()进行转换。

import pandas as pd

import numpy as np

# 通过to_datetime()直接转换为 datetime 类型

date1 = ['2012-05-06 11:00:00','2012-05-16 11:00:00']

pd_date1 = pd.to_datetime(date1)

df1 = pd.Series(np.random.randn(2),index=pd_date1)

print(pd_date1)

print(df1)

print('*'*20)

# 使用Datetimeindex()函数设置时间序

date2 = pd.DatetimeIndex(['1/1/2008', '1/2/2008', '1/3/2008', '1/4/2008', '1/5/2008'])

dt2 = pd.DataFrame(np.random.randn(5),index=date2, columns=['value'])

print(date2)

print(dt2)

# 输出结果

DatetimeIndex(['2012-05-06 11:00:00', '2012-05-16 11:00:00'], dtype='datetime64[ns]', freq=None)code>

2012-05-06 11:00:00 2.115566

2012-05-16 11:00:00 -0.145139

dtype: float64

********************

DatetimeIndex(['2008-01-01', '2008-01-02', '2008-01-03', '2008-01-04',

'2008-01-05'],

dtype='datetime64[ns]', freq=None)code>

value

2008-01-01 0.828022

2008-01-02 -1.873516

2008-01-03 1.940921

2008-01-04 1.563612

2008-01-05 0.964914

👁Timedelta时间差

Timedelta表示时间差(或者时间增量),我们可以使用不同的时间单位来表示它,比如,天、小时、分、秒。时间差的最终的结果可以是正时间差,也可以是负时间差。

import pandas as pd

import numpy as np

# 通过传递字符串可以创建Timedelta对象

print(pd.Timedelta('5 days 8 hours 6 minutes 59 seconds'))

# 通过传递整数值和unit参数也可以创建一个Timedelta对象。

print(pd.Timedelta(19,unit='h'))code>

# 数据偏移量, 比如,周(weeks)、天(days)、小时(hours)、分钟(minutes)、秒(milliseconds)、毫秒、微秒、纳秒都可以使用。

print(pd.Timedelta(days=2,hours=6))

print('*'*20)

# 您可以使用pd.to_timedelta()方法,将具有timedelta格式的值 (标量、数组、列表或Series)转换为Timedelta类型。如果输入是Series,则返回Series;如果输入是标量,则返回值也为标量,其他情况输出TimedeltaIndex。

print(pd.to_timedelta(['1 days 06:05:01.00003', '15.5us', 'nan']))

print(pd.to_timedelta(np.arange(5), unit='s'))code>

# 输出结果

5 days 08:06:59

0 days 19:00:00

2 days 06:00:00

********************

TimedeltaIndex(['1 days 06:05:01.000030', '0 days 00:00:00.000015', NaT], dtype='timedelta64[ns]', freq=None)code>

TimedeltaIndex(['00:00:00', '00:00:01', '00:00:02', '00:00:03', '00:00:04'], dtype='timedelta64[ns]', freq=None)code>

通过对datetime64[ns]类型的时间序列或时间戳做算术运算,其运算结果依然是datetime64[ns]数据类型。接下来,我们创建一个带有TimedeltadatetimeDataFrame对象,并对其做一些算术运算。

import pandas as pd

s = pd.Series(pd.date_range('2020-1-1', periods=5, freq='D'))code>

# 推导式用法

td = pd.Series([ pd.Timedelta(days=i) for i in range(5)])

df = pd.DataFrame(dict(A = s, B = td))

print(df)

print('*'*20)

# 加法运算

df['C']=df['A']+df['B']

print(df)

print('*'*20)

# 减法运算

df['D']=df['C']-df['B']

print(df)

# 输出结果

A B

0 2020-01-01 0 days

1 2020-01-02 1 days

2 2020-01-03 2 days

3 2020-01-04 3 days

4 2020-01-05 4 days

********************

A B C

0 2020-01-01 0 days 2020-01-01

1 2020-01-02 1 days 2020-01-03

2 2020-01-03 2 days 2020-01-05

3 2020-01-04 3 days 2020-01-07

4 2020-01-05 4 days 2020-01-09

********************

A B C D

0 2020-01-01 0 days 2020-01-01 2020-01-01

1 2020-01-02 1 days 2020-01-03 2020-01-02

2 2020-01-03 2 days 2020-01-05 2020-01-03

3 2020-01-04 3 days 2020-01-07 2020-01-04

4 2020-01-05 4 days 2020-01-09 2020-01-05

👀数据样本处理

👁Pandas缺失值处理

稀疏数据,指的是在数据库或者数据集中存在大量缺失数据或者空值,我们把这样的数据集称为稀疏数据集。稀疏数据不是无效数据,只不过是信息不全而已,只要通过适当的方法就可以“变废为宝”。

检查缺失值Pandas提供了isnull()notnull()两个函数,它们同时适用于SeriesDataFrame对象。

缺失数据计算:计算缺失数据时,需要注意两点:首先数据求和时,将NA值视为0,其次,如果要计算的数据为NA,那么结果就是NA。

清理并填充缺失值Pandas提供了多种方法来清除缺失值。fillna()函数可以实现用非空数据“填充”NaN值;ffill()向前填充和bfill()向后填充,使用这两个函数也可以处理NA值。replace()DataFrame中的通用值替换成特定值。

删除缺失值:使用dropna()函数与参数axis可以实现删除缺失值。在默认情况下,按照axis=0来按行处理,这意味着如果某一行中存在NaN值将会删除整行数据。

👁Pandas随机样本选择

随机抽样,是统计学中常用的一种方法,它可以帮助我们从大量的数据中快速地构建出一组数据分析模型。在Pandas中,如果想要对数据集进行随机抽样,需要使用sample()函数。该函数返回与数据集类型相同的新对象,相当于numpy.random.choice()

DataFrame.sample(n=None,frac=None,replace=False,weights=None,random_state=None,axis=None)

参数说明

n表示要抽取的行数。

frac表示抽取的比例,比如frac=0.5,代表抽取总体数据的50%。

replace布尔值参数,表示是否以有放回抽样的方式进行选择,默认为False,取出数据后不再放回。

weights可选参数,代表每个样本的权重值,参数值是字符串或者数组。

random_state 可选参数,控制随机状态,默认为None,表示随机数据不会重复;若为1表示会取得重复数据。

axis表示在哪个方向上抽取数据(axis=1表示列/axis=0表示行)。

👁Pandas数据重采样

数据重采样是将时间序列从一个频率转换至另一个频率的过程,它主要有两种实现方式,分别是降采样和升采样,降采样指将高频率的数据转换为低频率,升采样则与其恰好相反,说明如下:

方法 说明
降采样 将高频率(间隔短)数据转换为低频率(间隔长)。
升采样 将低频率数据转换为高频率。

Pandas提供了resample()函数来实现数据的重采样。

asfreq()方法不仅能够实现频率转换,还可以保留原频率对应的数值,同时它也可以单独使用。

插值处理,升采样的结果会产生缺失值,那么就需要对缺失值进行处理,一般有以下几种处理方式:

方法 说明
pad/ffill 用前一个非缺失值去填充缺失值。
backfill/bfill 用后一个非缺失值去填充缺失值。
interpolater('linear') 线性插值方法。
fillna(value) 指定一个值去替换缺失值。
👁Pandas分类对象

通常情况下,数据集中会存在许多同一类别的信息,比如相同国家、相同行政编码、相同性别等,当这些相同类别的数据多次出现时,就会给数据处理增添许多麻烦,导致数据集变得臃肿,不能直观、清晰地展示数据。

Pandas提供了分类对象(Categorical Object),该对象能够实现有序排列、自动去重的功能,但是它不能执行运算。通过Category的构造函数,您可以创建一个类别对象。

pandas.Categorical(values, categories, ordered)

参数说明

values:以列表的形式传参,表示要分类的值。

ordered:布尔值,默认为False,若为Ture,表示对分类的数据进行排序。

dtype:返回一个category类型,表示分类对象。

describe():对已经分类的数据使用describe()方法,得到和数据统计相关的摘要信息。

categories:使用obj.categories命令可以获取对象的类别信息。

Series.cat.categories:对类别实现重命名。

Series.cat.add_categories():追加新类别。

Series.cat.remove_categories():删除不需要的类别。

👀其它函数

👁Pandas统计函数

Pandas的本质是统计学原理在计算机领域的一种应用实现,通过编程的方式达到分析、描述数据的目的。而统计函数则是统计学中用于计算和分析数据的一种工具。在数据分析的过程中,使用统计函数有助于我们理解和分析数据。常见的统计函数,比如百分比函数、协方差函数、相关系数等。

pct_change()SeriesDatFrames都可以使用pct_change()函数。该函数将每个元素与其前一个元素进行比较,并计算前后数值的百分比变化。默认情况下,pct_change()对列进行操作,如果想要操作行,则需要传递参数axis=1参数。cov()Series对象提供了一个cov方法用来计算Series对象之间的协方差。同时,该方法也会将缺失值(NAN)自动排除。当应用于DataFrame时,协方差(cov)将计算所有列之间的协方差。corr():相关系数显示任意两个Series之间的线性关系。Pandas提供了计算相关性的三种方法,分别是pearson(default)spearman()kendall()。注意:如果DataFrame存在非数值(NAN),该方法会自动将其删除。rank() :按照某种规则(升序或者降序)对序列中的元素值排名,该函数的返回值的也是一个序列,包含了原序列中每个元素值的名次。如果序列中包含两个相同的的元素值,那么会为其分配两者的平均排名。

👁Pandas窗口函数

为了能更好地处理数值型数据,Pandas提供了几种窗口函数:

移动函数(rolling)扩展函数(expanding)指数加权函数(ewm

窗口是一种形象化的叫法,这些函数在执行操作时,就如同窗口一样在数据区间上移动。

如何在DataFrameSeries对象上应用窗口函数:

rolling() :移动窗口函数,它可以与meancountsummedianstd等聚合函数一起使用。

rolling(window=n, min_periods=None, center=False)

参数说明

window默认值为1,表示窗口的大小,也就是观测值的数量,

min_periods表示窗口的最小观察值,默认与window的参数值相等。

center是否把中间值做为窗口标准,默认值为False。

expanding() :扩展窗口函数,扩展是指由序列的第一个元素开始,逐个向后计算元素的聚合值。

ewm():(全称 Exponentially Weighted Moving)表示指数加权移动。ewn()函数先会对序列元素做指数加权运算,其次计算加权后的均值。该函数通过指定comspan或者halflife参数来实现指数加权移动。

在数据分析的过程中,使用窗口函数能够提升数据的准确性,并且使数据曲线的变化趋势更加平滑,从而让数据分析变得更加准确、可靠。

👁Pandas聚合函数

窗口函数可以与聚合函数一起使用,聚合函数指的是对一组数据求总和、最大值、最小值以及平均值的操作,本节重点讲解聚合函数的应用。

import pandas as pd

import numpy as np

data = { 'col1':[1,0,1,1],'col2':[0,2,5,0],'col3':[4,0,4,4],'col4':[1,0,1,1]}

df = pd.DataFrame(data)

print(df)

print("*"*20)

# 窗口大小为3,min_periods最小观测值为1

r1 = df.rolling(window=3,min_periods=1)

# min_periods默认与window的参数值相等

r2 = df.rolling(window=3)

print(r1.sum())

print(r2.sum())

print("*"*20)

# 把一个聚合函数传递给DataFrame

# 对整体聚合,使用aggregate()聚合操作

print(r1.aggregate(np.sum))

print("*"*20)

# 对任意某一列聚合

print(r1['col1'].aggregate(np.sum))

print("*"*20)

# 对多列数据聚合

print(r1['col1','col2'].aggregate(np.sum))

print("*"*20)

# 对单列应用多个函数

print(r1['col1'].aggregate([np.sum,np.mean]))

print("*"*20)

# 对不同列应用多个函数

print(r1['col1','col2'].aggregate([np.sum,np.mean]))

print("*"*20)

# 对不同列应用不同函数

print(r1.aggregate({ 'col1':np.sum,'col2':np.mean}))

# 输出结果

col1 col2 col3 col4

0 1 0 4 1

1 0 2 0 0

2 1 5 4 1

3 1 0 4 1

********************

col1 col2 col3 col4

0 1.0 0.0 4.0 1.0

1 1.0 2.0 4.0 1.0

2 2.0 7.0 8.0 2.0

3 2.0 7.0 8.0 2.0

col1 col2 col3 col4

0 NaN NaN NaN NaN

1 NaN NaN NaN NaN

2 2.0 7.0 8.0 2.0

3 2.0 7.0 8.0 2.0

********************

col1 col2 col3 col4

0 1.0 0.0 4.0 1.0

1 1.0 2.0 4.0 1.0

2 2.0 7.0 8.0 2.0

3 2.0 7.0 8.0 2.0

********************

0 1.0

1 1.0

2 2.0

3 2.0

Name: col1, dtype: float64

********************

col1 col2

0 1.0 0.0

1 1.0 2.0

2 2.0 7.0

3 2.0 7.0

********************

sum mean

0 1.0 1.000000

1 1.0 0.500000

2 2.0 0.666667

3 2.0 0.666667

********************

col1 col2

sum mean sum mean

0 1.0 1.000000 0.0 0.000000

1 1.0 0.500000 2.0 1.000000

2 2.0 0.666667 7.0 2.333333

3 2.0 0.666667 7.0 2.333333

********************

col1 col2

0 1.0 0.000000

1 1.0 1.000000

2 2.0 2.333333

3 2.0 2.333333

👁groupby分组操作

在数据分析中,经常会遇到这样的情况:根据某一列(或多列)标签把数据划分为不同的组别,然后再对其进行数据分析。比如,某网站对注册用户的性别或者年龄等进行分组,从而研究出网站用户的画像(特点)。在Pandas 中,要完成数据的分组操作,需要使用groupby()函数,它和SQLGROUP BY操作非常相似。 在划分出来的组(group)上应用一些统计函数,从而达到数据分析的目的,比如对分组数据进行聚合、转换,或者过滤。这个过程主要包含以下三步:

拆分(Spliting):表示对数据进行分组;应用(Applying):对分组数据应用聚合函数,进行相应计算;合并(Combining):最后汇总计算结果。

使用groupby()可以沿着任意轴分组。您可以把分组时指定的键(key)作为每组的组名,方法如下所示:

df.groupby("key")df.groupby("key",axis=1)df.groupby(["key1","key2"])

import pandas as pd

import numpy as np

data = { 'name': ['John', 'Helen', 'John', 'Ella'],

'score': [82, 98, 91, 87],

'option_course': ['C#','Python','Java','C']}

df = pd.DataFrame(data)

print(df)

print("*"*20)

# 生成分组groupby对象

print(df.groupby('score'))

print("*"*20)

# 查看分组,通过调用groups属性查看分组结果

print(df.groupby('score').groups)

print("*"*20)

# 多个列标签分组

print(df.groupby(['name','score']).groups)

print("*"*20)

# 通过 get_group()方法可以选择组内的具体数据项

print(df.groupby('score').get_group(91))

print("*"*20)

# 遍历分组数据

grouped=df.groupby('score')

for label, option_course in grouped:

# 其中key代表分组后字典的键,也就是score

print(label)

# 字典对应的值选修的科目

print(option_course)

print("*"*20)

# 通过agg()函数可以对分组对象应用多个聚合函数

grouped_name = df.groupby('name')

# 应用一个聚合函数求均值

print(grouped_name['score'].agg(np.mean))

# 应用多个聚合函数求均值

print(grouped_name['score'].agg([np.size,np.mean,np.std]))

print("*"*20)

# 组的数据过滤操作,筛选出名字出现超过两次的人名

print(grouped_name.filter(lambda x: len(x) >= 2))

# 输出结果

name score option_course

0 John 82 C#

1 Helen 98 Python

2 John 91 Java

3 Ella 87 C

********************

<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001CB3F4CD948>

********************

{ 82: Int64Index([0], dtype='int64'), 87: Int64Index([3], dtype='int64'), 91: Int64Index([2], dtype='int64'), 98: Int64Index([1], dtype='int64')}code>

********************

{ ('Ella', 87): Int64Index([3], dtype='int64'), ('Helen', 98): Int64Index([1], dtype='int64'), ('John', 82): Int64Index([0], dtype='int64'), ('John', 91): Int64Index([2], dtype='int64')}code>

********************

name score option_course

2 John 91 Java

********************

82

name score option_course

0 John 82 C#

87

name score option_course

3 Ella 87 C

91

name score option_course

2 John 91 Java

98

name score option_course

1 Helen 98 Python

********************

name

Ella 87.0

Helen 98.0

John 86.5

Name: score, dtype: float64

size mean std

name

Ella 1 87.0 NaN

Helen 1 98.0 NaN

John 2 86.5 6.363961

********************

name score option_course

0 John 82 C#

2 John 91 Java

组的转换操作:通过transform()函数可以实现组的转换,在组的行或列上可以执行转换操作,最终会返回一个与组大小相同的索引对象。

组的数据过滤操作:通过filter()函数可以实现数据的筛选,该函数根据定义的条件过滤数据并返回一个新的数据集。

👁merge合并操作

Pandas提供的merge()函数能够进行高效的合并操作,这与SQL关系型数据库的MERGE用法非常相似。从字面意思上不难理解,merge翻译为“合并”,指的是将两个DataFrame数据表按照指定的规则进行连接,最后拼接成一个新的DataFrame数据表。merge()函数的法格式如下:

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True,suffixes=('_x', '_y'), copy=True)code>

参数说明

left/right: 两个不同的DataFrame对象。

on: 指定用于连接的键(即列标签的名字),该键必须同时存在于左右两个DataFrame中,如果没有指定,并且其他参数也未指定, 那么将会以两个DataFrame的列名交集做为连接键。

left_on: 指定左侧DataFrame中作连接键的列名。该参数在左、右列标签名不相同,但表达的含义相同时非常有用。

right_on: 指定左侧DataFrame中作连接键的列名。

left_index: 布尔参数,默认为False。如果为True 则使用左侧DataFrame的行索引作为连接键,若DataFrame具有多层索引(MultiIndex),则层的数量必须与连接键的数量相等。

right_index: 布尔参数,默认为False。如果为True 则使用左侧DataFrame的行索引作为连接键。

how: 要执行的合并类型,从{ 'left','right','outer','inner'} 中取值,默认为“inner”内连接。

sort: 布尔值参数,默认为True,它会将合并后的数据进行排序;若设置为False,则按照how给定的参数值进行排序。

suffixes: 字符串组成的元组。当左右DataFrame存在相同列名时,通过该参数可以在相同的列名后附加后缀名,默认为('_x','_y')。

copy: 默认为True,表示对数据进行复制。

注意:Pandas库的merge()支持各种内外连接,与其相似的还有join()函数(默认为左连接)。

👁concat连接操作

Pandas通过concat()函数能够轻松地将SeriesDataFrame对象组合在一起,函数的语法格式如下:

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False)code>

参数说明

objs: 一个序列或者是Series、DataFrame对象。

axis: 表示在哪个轴方向上(行或者列)进行连接操作,默认axis=0表示行方向。

join: 指定连接方式,取值为{ "inner","outer"},默认为outer表示取并集,inner代表取交集。

ignore_index: 布尔值参数,默认为False,如果为True,表示不在连接的轴上使用索引。

join_axes: 表示索引对象的列表。

append(): 如果要连接SeriesDataFrame对象,有一个最方便、快捷的方法,就是append()方法。该方法沿着axis=0(行方向)进行操作;append()函数也可接收多个对象。

👀Pandas绘图

PandasMatplotlib绘图软件包的基础上单独封装了一个plot()接口,通过调用该接口可以实现常用的绘图操作。

import pandas as pd

import numpy as np

# 创建包含时间序列的数据

df = pd.DataFrame(np.random.randn(8,4),index=pd.date_range('2/1/2020',periods=8), columns=list('ABCD'))

df.plot()

# 如果行索引中包含日期,Pandas会自动调用gct().autofmt_xdate()来格式化x轴。

除了使用默认的线条绘图外,您还可以使用其他绘图方式,如下所示:

柱状图:bar()barh()直方图:hist()箱状箱:box()区域图:area()散点图:scatter()

通过关键字参数kind可以把上述方法传递给plot()

(1)柱状图

import pandas as pd

import numpy as np

df = pd.DataFrame(np.random.rand(10,4),columns=['a','b','c','d'])

# 或使用df.plot(kind="bar")code>

df.plot.bar()

# 通过设置参数stacked=True可以生成柱状堆叠图

# 或者使用df.plot.bar(stacked="True")code>

df.plot(kind="bar",stacked=True)code>

# 如果要绘制水平柱状图

df.plot.barh(stacked=True)

(2)直方图

plot.hist()可以实现绘制直方图,并且它还可以指定bins(构成直方图的箱数)。

import pandas as pd

import numpy as np

df = pd.DataFrame({ 'A':np.random.randn(100)+2,'B':np.random.randn(100),'C':np.random.randn(100)-2,'D':np.random.randn(100)+3},columns=['A', 'B', 'C','D'])

print(df)

# 指定箱数为15

df.plot.hist(bins=15)

# 给每一列数据都绘制一个直方图

df.diff().hist(color="r",alpha=0.5,bins=15)code>

(3)箱线图

通过调用Series.box.plot()DataFrame.box.plot()或者DataFrame.boxplot()方法来绘制箱型图,它将每一列数据的分布情况,以可视化的图像展现出来。

import pandas as pd

import numpy as np

df = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])

df.plot.box()

(4)区域图

使用Series.plot.area()DataFrame.plot.area()方法来绘制区域图。

import pandas as pd

import numpy as np

df = pd.DataFrame(np.random.rand(5, 4), columns=['a', 'b', 'c', 'd'])

df.plot.area()

(5)散点图

使用DataFrame.plot.scatter()方法来绘制散点图。

import pandas as pd

import numpy as np

df = pd.DataFrame(np.random.rand(30, 4), columns=['a', 'b', 'c', 'd'])

df.plot.scatter(x='a',y='b')code>

(6)饼状图

通过DataFrame.plot.pie()方法来绘制。

import pandas as pd

import numpy as np

df = pd.DataFrame(3 * np.random.rand(4), index=['go', 'java', 'c++', 'c'], columns=['L'])

df.plot.pie(subplots=True)

⛄Pandas和NumPy的比较

PandasNumPy被认为是科学计算与机器学习中必不可少的库,因为它们具有直观的语法和高性能的矩阵计算能力。

比较项 Pandas NumPy
适应性 Pandas主要用来处理类表格数据。 NumPy主要用来处理数值数据。
工具 Pandas提供了SeriesDataFrame数据结构。 NumPy构建了ndarray array来容纳数据。
性能 Pandas对于处理50万行以上的数据更具优势。 NumPy则对于50万以下或者更少的数据,性能更佳。
内存利用率 NumPy相比,Pandas会消耗大量的内存。 NumPy会消耗较少的内存。
对象 Pandas提供了DataFrame 2D数据表对象。 NumPy则提供了一个多维数组ndarray对象

在某些情况下,需要执行一些NumPy数值计算的高级函数,这个时候您可以使用to_numpy()函数,将DataFrame对象转换为NumPy ndarray数组,并将其返回。

DataFrame.to_numpy(dtype=None, copy=False)

参数说明如下:

dtype:可选参数,表示数据类型;

copy:布尔值参数,默认值为 Fales,表示返回值不是其他数组的视图。

import pandas as pd

#创建DataFrame对象

info = pd.DataFrame([[17,62,35],[25,36,54],[42,20,15],[48,62,76]], columns=['x','y','z'])

print('DataFrame\n----------\n', info)

#转换DataFrame为数组array

arr = info.to_numpy()

print('\nNumpy Array\n----------\n', arr)

# 输出结果

DataFrame

----------

x y z

0 17 62 35

1 25 36 54

2 42 20 15

3 48 62 76

Numpy Array

----------

[[17 62 35]

[25 36 54]

[42 20 15]

[48 62 76]]

多谢!多谢!

笔者不才,请多交流!!!

欢迎大家关注预览我的博客Blog:HeartLoveLife

能力有限,敬请谅解!!



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。