Python之Pandas详解
八秒记忆的老男孩 2024-08-02 16:33:06 阅读 99
<code>Pandas是Python
语言的一个扩展程序库,用于数据分析。
Pandas
是一个开放源码、BSD
许可的库,提供高性能、易于使用的数据结构和数据分析工具。
Pandas
名字衍生自术语 “panel data
”(面板数据)和 “Python data analysis
”(Python
数据分析)。
Pandas
一个强大的分析结构化数据的工具集,基础是NumPy
(提供高性能的矩阵运算)。
Pandas
可以从各种文件格式比如CSV
、JSON
、SQL
、Microsoft Excel
导入数据。
Pandas
可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。
Pandas
广泛应用在学术、金融、统计学等各个数据分析领域。
Pandas
主要包括以下几个特点:
它提供了一个简单、高效、带有默认标签(也可以自定义标签)的DataFrame
对象。能够快速从不同格式的文件中加载数据(比如 Excel
、CSV
、SQL
文件),然后转换为可处理的对象;能够按数据的行、列标签进行分组,并对分组后的对象执行聚合和转换操作;能够很方便地实现数据归一化操作和缺失值处理;能够很方便地对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
对象
ndarray
是NumPy
中的数组类型,当data
是ndarry
时,传递的索引必须具有与数组相同的长度。如果没有指定索引(隐式索引),索引值就从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)位置索引访问
这种访问方式与ndarray
和list
相同,使用元素自身的下标进行访问。我们知道数组的索引计数从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()
¬null()
检测缺失值
isnull()
和notnull()
用于检测Series
中的缺失值。所谓缺失值,顾名思义就是值不存在、丢失、缺少。
isnull()
:如果为值不存在或者缺失,则返回True
。notnull()
:如果值不存在或者缺失,则返回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)列索引删除数据列
通过del
和pop()
都能够删除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
都对应一个DataFrame
。major_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()
函数输出了平均值、std
和IQR
值(四分位距)等一系列统计信息。通过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()
方法允许您使用某些映射(dict
或Series
)或任意函数来对行、列标签重新命名,示例如下:
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
是如何遍历Series
和DataFrame
结构呢?对于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
用来指定排序算法。这里有三种排序算法:
mergesort
heapsort
quicksort
默认为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[]
只能使用整数索引,不能使用标签索引,通过整数索引切片选择数据时,前闭后开(不包含边界结束值)。同Python
和NumPy
一样,它们的索引都是从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]
数据类型。接下来,我们创建一个带有Timedelta
与datetime
的DataFrame
对象,并对其做一些算术运算。
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()
两个函数,它们同时适用于Series
和DataFrame
对象。
缺失数据计算:计算缺失数据时,需要注意两点:首先数据求和时,将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()
:Series
和DatFrames
都可以使用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
)
窗口是一种形象化的叫法,这些函数在执行操作时,就如同窗口一样在数据区间上移动。
如何在DataFrame
和Series
对象上应用窗口函数:
rolling()
:移动窗口函数,它可以与mean
、count
、sum
、median
、std
等聚合函数一起使用。
rolling(window=n, min_periods=None, center=False)
参数说明
window默认值为1,表示窗口的大小,也就是观测值的数量,
min_periods表示窗口的最小观察值,默认与window的参数值相等。
center是否把中间值做为窗口标准,默认值为False。
expanding()
:扩展窗口函数,扩展是指由序列的第一个元素开始,逐个向后计算元素的聚合值。
ewm()
:(全称 Exponentially Weighted Moving)表示指数加权移动。ewn()
函数先会对序列元素做指数加权运算,其次计算加权后的均值。该函数通过指定com
、span
或者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()
函数,它和SQL
的GROUP 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()
函数能够轻松地将Series
与DataFrame
对象组合在一起,函数的语法格式如下:
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()
: 如果要连接Series
和DataFrame
对象,有一个最方便、快捷的方法,就是append()
方法。该方法沿着axis=0
(行方向)进行操作;append()
函数也可接收多个对象。
👀Pandas绘图
Pandas
对Matplotlib
绘图软件包的基础上单独封装了一个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的比较
Pandas
和NumPy
被认为是科学计算与机器学习中必不可少的库,因为它们具有直观的语法和高性能的矩阵计算能力。
比较项 | Pandas | NumPy |
---|---|---|
适应性 | Pandas 主要用来处理类表格数据。 | NumPy 主要用来处理数值数据。 |
工具 | Pandas 提供了Series 和DataFrame 数据结构。 | 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
能力有限,敬请谅解!!
上一篇: ES 8.14 向量搜索优化
下一篇: [notice] A new release of pip is available: 24.0 -> 24.1.2[notice] To update, run: python.exe -m pi
本文标签
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。