Pandas
1、Pandas是什么
安装依赖:pip install pandas
导入:import pandas as pd
1.1、Panda概述
Pandas 是一个基于 Python 的数据分析库,提供了用于处理结构化数据的丰富的数据结构和数据操作工具。它特别适用于数据清洗、数据转换、数据分析和数据可视化等任务 (中文学习网站)
1.2、Panda特点
① 它提供了一个简单、高效、带有默认标签(也可以自定义标签)的 DataFrame 对象
② 能够快速得从不同格式的文件中加载数据(比如 Excel、CSV 、SQL文件),然后将其转换为可处理的对象
③ 能够按数据的行、列标进行分组,并对分组后的对象执行聚合和转换操作
④ 能够很方便地实现数据归一化操作和缺失值处理
⑤ 能够很方便地对 DataFrame 的数据列进行增加、修改或者删除的操作
⑥ 能够处理不同格式的数据集,比如矩阵数据、异构数据表、时间序列等
⑦ 提供了多种处理数据集的方式,比如构建子集、切片、过滤、分组以及重新排序等
1.3、Pandas和Numpy的一些区别
① 数据结构
NumPy 主要提供了多维数组对象 ndarray,它是一个固定大小的数组,所有元素的类型都相同
Pandas 提供了两种主要的数据结构:Series 和 DataFrame。Series 是一维标记数组,类似于 NumPy 的一维数组;而 DataFrame 是二维标记数据结构,类似于电子表格或数据库表格
② 用途:
NumPy 主要用于数值计算和科学计算领域,提供了高性能的数值运算功能,如数组运算、线性代数运算、傅里叶变换等
Pandas 主要用于数据分析和数据处理领域,提供了丰富的数据操作工具,包括数据清洗、数据转换、数据分组、数据聚合、数据可视化等功能
③ 数据处理能力:
NumPy 更适合处理数值型数据,提供了丰富的数值运算函数和方法
Pandas 更适合处理结构化数据,如表格型数据、时间序列数据等,提供了灵活的数据操作和分析工具
比较项 | Pandas | NumPy |
---|---|---|
适应性 | Pandas主要用来处理类表格数据 | NumPy 主要用来处理数值数据 |
工具 | Pandas提供了Series和DataFrame数据结构 | NumPy 构建了 ndarray array来容纳数据 |
性能 | Pandas对于处理50万行以上的数据更具优势 | NumPy 则对于50万以下或者更少的数据,性能更佳 |
内存利用率 | 与 NumPy相比,Pandas会消耗大量的内存 | NumPy 会消耗较少的内存 |
对象 | Pandas 提供了 DataFrame 2D数据表对象 | NumPy 则提供了一个多维数组 ndarray 对象 |
Pandas的DataFrame对象转换成ndarray的方法:to_numpy()
import pandas as pd
# 构建DataFrame对象
df = pd.DataFrame({"P": [2, 3], "Q": [4.0, 5.8]})
df['R'] = pd.date_range('2020-12-23', periods=2) # 再添加一列
print(df)
print('-' * 30)
# 转化为numpy数组
n = df.to_numpy()
print(n)
2、Pandas的数据结构 —— Series
2.1、Series概述
Pandas 中的 Series 是一种一维标记数组,类似于 Python 中的字典或者 NumPy 中的一维数组。它由一组数据和一组与之相关联的索引(标签)组成,可以存储任意类型的数据,并且索引可以是任意类型的
2.2、Series创建
① 使用列表创建
import pandas as pd
list1 = [1, 2, 3, 4]
s1 = pd.Series(list1)
print(s1)
0 1
1 2
2 3
3 4
dtype: int64
② 使用ndarray对象创建
import pandas as pd
import numpy as np
arr = np.array([1, 2, 3, 4])
s1 = pd.Series(arr, index=['A', 'B', 'C', 'D']) # 可以使用index来指定索引
print(s1)
A 1
B 2
C 3
D 4
dtype: int32
③ 使用字典创建
import pandas as pd
s1 = pd.Series({'name': 'hyh', 'age': 18, 'gender': 'boy'})
print(s1)
name hyh
age 18
gender boy
dtype: object
④ 使用标量创建
import pandas as pd
s1 = pd.Series(4, index=['a', 'b', 'c', 'd'])
print(s1)
a 4
b 4
c 4
d 4
dtype: int64
2.3、Series的常用属性
属性 | 描述 |
---|---|
values | 以ndarray的形式返回数据 |
index | 索引,是一个Index对象 |
axes | 每个轴的索引,是一个Index对象数组 |
size | 长度 |
ndim | 数据的维度 |
dtype | 数据类型 |
import pandas as pd
l1 = [1, 2, 3, 4]
s = pd.Series(l1, index=['a', 'b', 'c', 'd'])
print("Series:\n", s)
print('-' * 30)
# 访问数据
print(s.values, type(s.values))
print('-' * 30)
# 访问索引
print(s.index, list(s.index))
print('-' * 30)
# 访问每个轴的索引
print(s.axes, s.axes[0] is s.index)
print('-' * 30)
# 访问大小
print(s.size)
print('-' * 30)
# 访问维度
print(s.ndim)
print('-' * 30)
# 访问数据类型
print(s.dtype)
Series:
a 1
b 2
c 3
d 4
dtype: int64
------------------------------
[1 2 3 4] <class 'numpy.ndarray'>
------------------------------
Index(['a', 'b', 'c', 'd'], dtype='object') ['a', 'b', 'c', 'd']
------------------------------
[Index(['a', 'b', 'c', 'd'], dtype='object')] True
------------------------------
4
------------------------------
1
------------------------------
int64
2.4、Series的常用方法
说明:下方的ser代指Series的实例对象
方法 | 描述 |
---|---|
ser.head(num) | 前num行数据 |
ser.tail(num) | 尾num行数据 |
pd.isnull(ser) pd.nonull(ser) | 检测是否有缺失值,返回的是一个Series对象 |
import pandas as pd
import numpy as np
arr = np.random.randint(1, 10, 5)
s = pd.Series(arr)
print(s)
print('-' * 30)
print(s.head(2))
print('-' * 30)
print(s.tail(2))
print('-' * 30)
print(pd.isnull(s))
print('-' * 30)
0 8
1 1
2 4
3 2
4 4
dtype: int32
------------------------------
0 8
1 1
dtype: int32
------------------------------
3 2
4 4
dtype: int32
0 False
1 False
2 False
3 False
4 False
dtype: bool
3、Pandas的数据结构 —— DataFrame
3.1、DataFrame概述
DataFrame 是 Pandas 中最重要的数据结构之一,它是一个二维标记数据结构,类似于电子表格或者数据库中的表格。DataFrame 由行和列组成,每一列可以是不同的数据类型(例如整数、浮点数、字符串等),并且每一行和每一列都有对应的标签索引
3.2、DataFrame创建
① 使用列表创建
import pandas as pd
list1 = [1, 2]
df = pd.DataFrame(list1)
print(df)
print('-' * 30)
list2 = [('Alex', 11), ('Bob', 12), ('Clarke', 13)]
df = pd.DataFrame(list2, columns=['name', 'age'], dtype=float)
print(df)
0
0 1
1 2
------------------------------
name age
0 Alex 11.0
1 Bob 12.0
2 Clarke 13.0
② 使用字典嵌套列表创建
import pandas as pd
data1 = {'name': ['Tom', 'Jack', 'Steve', 'Hyh'], 'age': [28, 48, 61, 15]}
df = pd.DataFrame(data1)
print(df)
data2 = {'name': ['Pyy', 'Zayn', 'Yh'], 'age': [32, 51, 23]}
df = pd.DataFrame(data2, index=['rank1', 'rank2', 'rank3'])
print(df)
name age
0 Tom 28
1 Jack 48
2 Steve 61
3 Hyh 15
name age
rank1 Pyy 32
rank2 Zayn 51
rank3 Yh 23
③ 使用列表嵌套字典创建
import pandas as pd
data1 = [{'name': 'Pyy', 'age': 22}, {'name': 'Zayn', 'age': 31, 'gender': 'boy'}]
df = pd.DataFrame(data1)
print(df)
print('-' * 30)
data1 = [{'name': 'Pyy', 'age': 22}, {'name': 'Zayn', 'age': 31, 'gender': 'boy'}]
df = pd.DataFrame(data1, index=['first', 'second'], columns=['age', 'name'])
print(df)
name age gender
0 Pyy 22 NaN
1 Zayn 31 boy
------------------------------
age name
first 22 Pyy
second 31 Zayn
④ 使用字典嵌套Series创建
import pandas as pd
ser1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
ser2 = pd.Series([2, 3, 4, 5], index=['b', 'c', 'd', 'e'])
arr = {'one': ser1, 'two': ser2}
df = pd.DataFrame(arr)
print(df)
one two
a 1.0 NaN
b 2.0 2.0
c 3.0 3.0
d NaN 4.0
e NaN 5.0
3.3、列索引操作DataFrame
import pandas as pd
ser1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
ser2 = pd.Series([2, 3, 4, 5], index=['b', 'c', 'd', 'e'])
arr = {'one': ser1, 'two': ser2}
df = pd.DataFrame(arr)
print(df)
print('-' * 30)
# 访问一列,返回的是一个Series对象
print(df['one'])
print('-' * 30)
# 访问多列,返回的是一个DataFrame对象
print(df[['one', 'two']])
print('-' * 30)
# 添加一列
df['three'] = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
df.insert(loc=1, column='four', value=[40, 50, 60, 70, 80]) # insert的数据长度要同现有的index长度
print(df)
print('-' * 30)
# 删除一列
df.pop('four')
print(df)
one two
a 1.0 NaN
b 2.0 2.0
c 3.0 3.0
d NaN 4.0
e NaN 5.0
------------------------------
a 1.0
b 2.0
c 3.0
d NaN
e NaN
Name: one, dtype: float64
------------------------------
one two
a 1.0 NaN
b 2.0 2.0
c 3.0 3.0
d NaN 4.0
e NaN 5.0
------------------------------
one four two three
a 1.0 40 NaN 10.0
b 2.0 50 2.0 20.0
c 3.0 60 3.0 30.0
d NaN 70 4.0 NaN
e NaN 80 5.0 NaN
------------------------------
one two three
a 1.0 NaN 10.0
b 2.0 2.0 20.0
c 3.0 3.0 30.0
d NaN 4.0 NaN
e NaN 5.0 NaN
3.4、行索引操作DataFrame
import pandas as pd
ser1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
ser2 = pd.Series([2, 3, 4, 5], index=['b', 'c', 'd', 'e'])
arr = {'one': ser1, 'two': ser2}
df = pd.DataFrame(arr)
print(df)
print('-' * 30)
# 使用切片访问行
print(df[1:4])
print('-' * 30)
# 使用loc访问行,需要使用行的标签名
print(df.loc['b'], '\n', dict(df.loc['b']))
print('-' * 30)
# 使用iloc访问行,需要使用行的位置索引
print(df.iloc[3], '\n', dict(df.iloc[3]))
print('-' * 30)
# 添加
newrow = pd.DataFrame([[10, 20], [30, 40]], columns=['one', 'two'], index=['f', 'g'])
df = df.append(newrow)
print(df)
print('-' * 30)
# 删除
df = df.drop('b')
print(df)
one two
a 1.0 NaN
b 2.0 2.0
c 3.0 3.0
d NaN 4.0
e NaN 5.0
------------------------------
one two
b 2.0 2.0
c 3.0 3.0
d NaN 4.0
------------------------------
one 2.0
two 2.0
Name: b, dtype: float64
{'one': 2.0, 'two': 2.0}
------------------------------
one NaN
two 4.0
Name: d, dtype: float64
{'one': nan, 'two': 4.0}
------------------------------
one two
a 1.0 NaN
b 2.0 2.0
c 3.0 3.0
d NaN 4.0
e NaN 5.0
f 10.0 20.0
g 30.0 40.0
------------------------------
one two
a 1.0 NaN
c 3.0 3.0
d NaN 4.0
e NaN 5.0
f 10.0 20.0
g 30.0 40.0
3.5、条件查询、索引器查询
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(1, 10, (4, 4)),
columns=['c1', 'c2', 'c3', 'c4'],
index=['i1', 'i2', 'i3', 'i4'])
print(df)
print('-' * 30)
# 条件索引
print(df[df['c1'] >= 5])
print('-' * 30)
# 多条件
print(df[(df['c1'] >= 5) & (df['c3'] <= 5)])
print('-' * 30)
# 索引器,其实也就是loc和iloc,首先传入行,再传入列
print(df.loc[['i1', 'i3'], ['c2', 'c4']])
print('-' * 30)
print(df.loc[df['c1'] >= 5, ['c2', 'c4']])
print('-' * 30)
print(df.iloc[0:2, 1:3])
#运行结果
c1 c2 c3 c4
i1 1 5 8 9
i2 1 2 3 3
i3 4 9 5 7
i4 7 9 1 4
------------------------------
c1 c2 c3 c4
i4 7 9 1 4
------------------------------
c1 c2 c3 c4
i4 7 9 1 4
------------------------------
c2 c4
i1 5 9
i3 9 7
------------------------------
c2 c4
i4 9 4
------------------------------
c2 c3
i1 5 8
i2 2 3
3.6、DataFrame的常用方法
方法 | 描述 |
---|---|
rename(columns,index,inplace) | 修改行名、列名 columns:修改列名,index:修改行名,inplace:是否在原数据中进行修改,默认为False |
insert(loc,column,value,allow_duplicates) | 插入列 loc:插入的位置,column:列名,value:值,allow_duplicates是否允许列名重复,默认为False |
drop(labels,axis,index,inplace) | 删除 labels:行/列的名,index:行/列的位置(与labels等效,两者选一),axis:删除行还是列,默认为0表示删除行,inplace:是否在原数据上删除,默认为False |
head(n)、tail(n) | 首尾n行 |
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(1, 10, (4, 4)),
columns=['c1', 'c2', 'c3', 'c4'],
index=['i1', 'i2', 'i3', 'i4'])
# 原数组
print(df)
print('-' * 30)
# 修改行列名
df.rename(index={'i1': 0, 'i2': 1}, inplace=True) # 修改行名
df.rename(columns={'c1': '3', 'c2': '4'}, inplace=True) # 修改列名
print(df)
print('-' * 30)
# 插入列
df.insert(loc=2, column='5', value=[100, 200, 300, 400])
print(df)
print('-' * 30)
# 删除行列
df.drop(axis=0, labels='i3', inplace=True) # 删除行
df.drop(axis=1, labels='5', inplace=True) # 删除列
print(df)
print('-' * 30)
# 获取首行和尾两行
print(df.head(1))
print('-' * 30)
print(df.tail(2))
#运行结果
c1 c2 c3 c4
i1 7 9 5 3
i2 2 8 2 6
i3 7 9 7 7
i4 5 7 5 9
------------------------------
3 4 c3 c4
0 7 9 5 3
1 2 8 2 6
i3 7 9 7 7
i4 5 7 5 9
------------------------------
3 4 5 c3 c4
0 7 9 100 5 3
1 2 8 200 2 6
i3 7 9 300 7 7
i4 5 7 400 5 9
------------------------------
3 4 c3 c4
0 7 9 5 3
1 2 8 2 6
i4 5 7 5 9
------------------------------
3 4 c3 c4
0 7 9 5 3
------------------------------
3 4 c3 c4
1 2 8 2 6
i4 5 7 5 9
3.7、DataFrame的常用属性
属性 | 描述 |
---|---|
head(num)、tail(num) | 前num行、后num行数据 |
values | 返回数据,是一个二维的ndarray数组 |
size | 元素的元素数量(不是行数,一行可能包含多个元素) |
axes | 返回包含行标签、列标签的列表 |
ndim | 轴的数量 |
shape | 返回一个元组,表示DataFrame的维度 |
dtypes | 返回每列数据的数据类型 |
T | 转置 |
shift(peroids,freq,axis,fill_value) | 将行/列移动指定步幅长度 peroids类型为int,表示移动的幅度,默认为1,正数表示向下/右移动 freq表示日期偏移量,适用于时间序,默认为None axis为0表示上下移动,为1表示左右移动,默认为0 fill_value用来填充缺失值 |
import pandas as pd
df = pd.DataFrame({'a_data': [28, 71, 37, 16, 58], 'b_data': [35, 25, 17, 39, 54], 'c_data': [36, 51, 34, 56, 71]})
print(df)
print('-' * 30)
df = df.shift(periods=1).shift(periods=1, axis=1)
print(df)
print('-' * 30)
df = df.shift(periods=1, axis=1, fill_value='a')
print(df)
a_data b_data c_data
0 28 35 36
1 71 25 51
2 37 17 34
3 16 39 56
4 58 54 71
------------------------------
a_data b_data c_data
0 NaN NaN NaN
1 NaN 28.0 35.0
2 NaN 71.0 25.0
3 NaN 37.0 17.0
4 NaN 16.0 39.0
------------------------------
a_data b_data c_data
0 a NaN NaN
1 a NaN 28
2 a NaN 71
3 a NaN 37
4 a NaN 16
3.8、统计函数
方法 | 描述 |
---|---|
count() | 统计非空值的数量 |
sum() | 求和 |
mean() | 均值 |
median() | 中位数 |
mode() | 众数 |
std() | 标准差 |
min() | 最小值 |
max() | 最大值 |
abs() | 绝对值 |
prod() | 所有数值的乘积 |
cumsum() | axis=0:按行累加,axis=1:按列累加 |
cumprod() | axis=0:按行累积,axis=1:按列累积 |
corr() | 计算数列或变量之间的相关系数,取值-1到1,越接近1相关性越强 |
describe(include=‘all’) | 统计信息摘要 |
import pandas as pd
# 创建字典型series结构
d = {'Name': pd.Series(['小明', '小亮', '小红', '小华', '老赵', '小曹', '小陈',
'老李', '老王', '小冯', '小何', '老张']),
'Age': pd.Series([25, 26, 25, 23, 30, 29, 23, 34, 40, 30, 51, 46]),
'Rating': pd.Series([4.23, 3.24, 3.98, 2.56, 3.20, 4.6, 3.8, 3.78, 2.98, 4.80, 4.10, 3.65])
}
df = pd.DataFrame(d)
print(df)
print('-' * 30)
print(df.sum())
print('-' * 30)
print(df.sum(axis=1))
print('-' * 30)
print(df.describe(include='all'))
Name Age Rating
0 小明 25 4.23
1 小亮 26 3.24
2 小红 25 3.98
3 小华 23 2.56
4 老赵 30 3.20
5 小曹 29 4.60
6 小陈 23 3.80
7 老李 34 3.78
8 老王 40 2.98
9 小冯 30 4.80
10 小何 51 4.10
11 老张 46 3.65
------------------------------
Name 小明小亮小红小华老赵小曹小陈老李老王小冯小何老张
Age 382
Rating 44.92
dtype: object
------------------------------
0 29.23
1 29.24
2 28.98
3 25.56
4 33.20
5 33.60
6 26.80
7 37.78
8 42.98
9 34.80
10 55.10
11 49.65
dtype: float64
------------------------------
Name Age Rating
count 12 12.000000 12.000000
unique 12 NaN NaN
top 小亮 NaN NaN
freq 1 NaN NaN
mean NaN 31.833333 3.743333
std NaN 9.232682 0.661628
min NaN 23.000000 2.560000
25% NaN 25.000000 3.230000
50% NaN 29.500000 3.790000
75% NaN 35.500000 4.132500
max NaN 51.000000 4.800000
4、Pandas绘图 —— plot
4.1、plot介绍
DataFrame.plot(x=None, y=None, kind='line', ax=None, subplots=False,
sharex=None, sharey=False, layout=None, figsize=None,
use_index=True, title=None, grid=None, legend=True,
style=None, logx=False, logy=False, loglog=False,
xticks=None, yticks=None, xlim=None, ylim=None, rot=None,
fontsize=None, colormap=None, position=0.5, table=False, yerr=None,
xerr=None, stacked=True/False, sort_columns=False,
secondary_y=False, mark_right=True, **kwds)
plot 函数是 Pandas 中的一个函数,用于绘制数据的图表。它是基于 Matplotlib 库实现的,能够直接在 Pandas 的 Series 和 DataFrame 对象上使用,提供了一种简单而强大的数据可视化功能。plot 函数可以绘制多种类型的图表,如折线图、柱状图、散点图、箱线图等,具体的图表类型由 kind 参数指定, 使用DataFrame的plot方法绘制图像会按照数据的每一列绘制一条曲线,默认按照列columns的名称在适当的位置展示图例,比matplotlib绘制节省时间,且DataFrame格式的数据更规范,方便向量化及计算
4.2、plot主要参数
参数 | 描述 |
---|---|
kind | 绘图类型 line:折线图、bar:条形图(Stacked=True时为堆叠柱状图)、barh:横向条形图 hist:直方图、box:箱型图、area:面积图(Stacked=True时,每列的正负性要相同) kde:密度图、pie:饼状图、scatter:散点图、hexbin:蜂巢图 |
subplots | 指定图表的行数和列数,从而创建一个由多个子图组成的矩阵式布局 搭配layout可以设置子图的布局 |
grid | 显示或隐藏网格线 |
legend | 图例,用于解释图表中各个数据系列的含义 |
logx | 在 x 轴上使用对数刻度 |
logy | 在 y 轴上使用对数刻度 |
loglog | 在 x 轴和 y 轴上同时使用对数刻度 |
xlim&ylim | 设置 x 轴和 y 轴的刻度范围。可以传递一个包含两个元素的列表或元组,分别表示轴的最小值和最大值 |
fontsize | 设置图表中的字体大小 |
style / color / colors | 自定义颜色,不同的统计图可能需要的参数不一样 |
secondary_y | 设置右边的y轴 |
4.3、折线图
4.3.1、折线图
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
# 生成一千条符合标准正太分布的数据(此时数据扎堆在0附近),index是日期,列名记为ABCD
df = pd.DataFrame(np.random.randn(1000, 4), index=pd.date_range('1/1/2000', periods=1000), columns=list('ABCD'))
print(df)
print('-' * 30)
# 对原数组的数据做下改造,使不会扎堆在0附近
df = df.cumsum()
print(df)
print('-' * 30)
# df.plot用于构建成一个图表对象(AxesSubplot),行索引做x轴,列数表示有几条数据
# 若行索引index中包含日期,Pandas 会自动调用 gct().autofmt_xdate() 来格式化x轴
df.plot(kind='line', # 折线图
grid=True, # 显示表格
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'], # 自定义颜色
)
# 将现有的图表对象显示出来
plt.show()
4.3.2、多个子图
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
# 生成一千条符合标准正太分布的数据(此时数据扎堆在0附近),index是日期,列名记为ABCD
df = pd.DataFrame(np.random.randn(1000, 4), index=pd.date_range('1/1/2000', periods=1000), columns=list('ABCD'))
print(df)
print('-' * 30)
# 对原数组的数据做下改造,使不会扎堆在0附近
df = df.cumsum()
print(df)
print('-' * 30)
# df.plot用于构建成一个图表对象(AxesSubplot),行索引做x轴,列数表示有几条数据
# 若行索引index中包含日期,Pandas 会自动调用 gct().autofmt_xdate() 来格式化x轴
df.plot(kind='line', # 折线图
grid=True, # 显示表格
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'], # 自定义颜色
subplots=True # 每列数据在一个子图中展示
)
# 将现有的图表对象显示出来
plt.show()
4.3.3、多个子图任意排列
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
# 生成一千条符合标准正太分布的数据(此时数据扎堆在0附近),index是日期,列名记为ABCD
df = pd.DataFrame(np.random.randn(1000, 4), index=pd.date_range('1/1/2000', periods=1000), columns=list('ABCD'))
print(df)
print('-' * 30)
# 对原数组的数据做下改造,使不会扎堆在0附近
df = df.cumsum()
print(df)
print('-' * 30)
# df.plot用于构建成一个图表对象(AxesSubplot),行索引做x轴,列数表示有几条数据
# 若行索引index中包含日期,Pandas 会自动调用 gct().autofmt_xdate() 来格式化x轴
df.plot(kind='line', # 折线图
grid=True, # 显示表格
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'], # 自定义颜色
subplots=True, # 每列数据在一个子图中展示
layout=(2, 2) # 子图布局
)
# 将现有的图表对象显示出来
plt.show()
4.3.4、主副轴设置
import numpy as np
import pandas as pd
from matplotlib.axes._subplots import Axes
from matplotlib import pyplot as plt
df = pd.DataFrame(np.random.randn(1000, 4), index=pd.date_range('1/1/2000', periods=1000), columns=list('ABCD'))
df = df.cumsum()
# 编辑代码时,Pycharm不知道df.plot返回的是个什么东西,因此可以用ax:Axes来指明,这样下面使用ax的属性方法时,Pycharm才会有提示
ax: Axes = df.plot(kind='line',
grid=True,
style=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'], # 自定义颜色
secondary_y=['A', 'B'], # 将AB列放在副轴上
)
# 使用图表对象的方法来修改图表
ax.set_ylabel('CD scale') # 主轴名
ax.legend(loc='upper left') # 主轴的标签显示在左上
ax.right_ax.set_ylabel('AB scale') # 副轴名
ax.right_ax.legend(loc='upper right') # 副轴的标签显示在右上
# 将现有的图表对象显示出来
plt.show()
4.4、条形图
4.4.1、显示Series数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
# 设置中文字体为宋体,因为要在图中显示文字
matplotlib.rcParams['font.family'] = ['SimSun']
# 创建一个 2x2 的子图布局,返回的是画布和子图对象数组
fig, axes = plt.subplots(nrows=2, ncols=2)
# 创建十组数据
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
# axes.flat返回每个子图对象,enumerate能在遍历的同时返回下标
for i, ax in enumerate(axes.flat):
df.iloc[i].plot(kind='bar', # 柱状图
ax=ax, # 将结果赋值给画布上的子图
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'], # 自定义颜色
) # 自定义颜色
ax.set_title('第 {} 组数据'.format(i)) # 设置子图标题
# 显示
plt.show()
4.4.2、显示DateFrame数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建四数据
df = pd.DataFrame(np.random.rand(4, 4), columns=['a', 'b', 'c', 'd'])
df.plot(kind='bar', color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'])
# 显示
plt.show()
Tip:对于Series数据,每个标签占一个bar,标签之间会有分隔,对于DataFrame数据,每组数据占一组bar,每组数据之间会有分隔
4.4.3、堆积条形图
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建四数据
df = pd.DataFrame(np.random.rand(4, 4), columns=['a', 'b', 'c', 'd'])
df.plot(kind='bar',
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'],
stacked=True)
# 显示
plt.show()
4.4.4、水平条形图
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建四数据
df = pd.DataFrame(np.random.rand(4, 4), columns=['a', 'b', 'c', 'd'])
df.plot(kind='barh',
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'],
stacked=True)
# 显示
plt.show()
4.4.5、直方图
直方图常用于以下情况:
① 展示数据的分布情况:直方图可以直观地展示数据的分布特征,如数据的中心位置、离散程度、偏态和峰度等。
② 检查数据的异常值:直方图可以帮助识别数据中的异常值,例如是否有超出正常范围的极端值。
③ 分析数据的特征:直方图可以帮助理解数据的特征,如数据的集中程度、分布形态等,从而为后续的数据分析和建模提供参考。
通过观察直方图,可以快速了解数据的整体分布情况,有助于进一步的数据分析和决策
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建四数据
df = pd.DataFrame(np.random.rand(4, 4), columns=['a', 'b', 'c', 'd'])
print(df)
df.plot(kind='hist',
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'])
# 显示
plt.show()
4.4.6、箱式图
箱线图通常包含以下几个部分:
① 箱体(Box):箱体表示数据的四分位数范围,箱体的上边界是数据的第三四分位数(Q3:75%),下边界是数据的第一四分位数(Q1:25%),箱体内部的水平线表示数据的中位数(Q2:50%),例如65,70,72,75,78,80,82,85,88,90的Q1=1025%=2.5=>第3位:72;Q2=中位数=(75+78)/2=76.5;Q3=1075%=7.5=>第8位:85;因此箱体的范围占数据的一半25%~75%
② 上限(Whisker):上限和下限表示数据的边界,它们通常是箱体顶部和底部的最大值和最小值,但也可以根据具体的定义方式而有所不同。上限和下限之外的数据点称为离群值(Outlier)
箱线图常用于以下情况:
① 观察数据的分布情况:箱线图可以帮助识别数据的中位数、四分位数以及离群值,从而了解数据的分布特征
② 比较不同组数据的分布:箱线图可以同时展示多个组的数据分布情况,方便比较不同组之间的差异和相似性
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建十条数据
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
print(df)
df.plot(kind='box')
# 显示
plt.show()
4.5、面积图
4.5.1、堆积型
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建十条数据
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
print(df)
df.plot(kind='area',
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'])
# 显示
plt.show()
4.5.2、非堆积型
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建十条数据
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
print(df)
df.plot(kind='area',
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'],
stacked=False)
# 显示
plt.show()
4.6、饼状图
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建四条数据
df = pd.DataFrame(np.random.rand(4, 4), columns=['P1', 'P2', 'P3', 'P4'], index=['a', 'b', 'c', 'd'])
df.plot(kind='pie',
colors=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'], # 自定义颜色
subplots=True,
layout=(2, 2),
figsize=(8, 6))
# 显示
plt.show()
4.7、核密度图
核密度估计图:一种用于估计概率密度函数的非参数方法,它可以帮助我们了解数据的分布情况,是在直方图的基础上进行了平滑处理,它使用核函数(通常是高斯核函数)对每个数据点附近的概率密度进行估计,并将所有核函数的估计值进行叠加,最终得到一条连续的曲线,表示数据的概率密度函数。核密度图可以提供比直方图更平滑的数据分布曲线,帮助我们更直观地了解数据的分布特征
安装依赖(使用该模块来计算核密度):pip install scipy
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
# 创建一个 2x2 的子图布局,返回的是画布和子图对象数组
fig, axes = plt.subplots(nrows=1, ncols=2)
# 创建20条数据
df = pd.DataFrame(np.random.rand(20, 4), columns=['a', 'b', 'c', 'd'])
df2 = df.copy()
# 核密度图
df.plot(kind='kde',
ax=axes[0],
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'],
figsize=(14, 6))
# 对应的直方图
df2.plot(kind='hist',
bins=20,
ax=axes[1],
color=['#79CDCD', '#EEB4B4', '#6CA6CD', '#FFA54F'],
figsize=(14, 6))
# 显示
plt.show()
5、读写文件
5.1、CSV 是什么
CSV(Comma-Separated Values)是一种常用的文本文件格式,用于存储表格数据。在 CSV 文件中,数据以逗号或其他分隔符(如分号、制表符等)分隔,每行代表表格中的一行数据记录,每个字段代表记录中的一个属性值,CSV 文件通常以 .csv 扩展名结尾,它是一种通用的数据交换格式,可以被几乎所有的数据处理软件和编程语言所支持
5.2、CSV 文件的优点
① 简单易用:CSV 文件使用纯文本格式存储数据,易于创建和编辑,且通用性强
② 跨平台兼容:CSV 文件可以在不同操作系统和软件之间进行数据交换,具有较好的跨平台兼容性
③ 轻量级:CSV 文件相比于其他数据存储格式(如 Excel 文件)通常更加轻量级,存储效率高
5.3、CSV 文件的缺点
① 不支持复杂数据结构:CSV 文件仅支持平面表格数据的存储,不支持复杂的数据结构(如嵌套表格、多表关联等)
② 不支持元数据:CSV 文件不支持存储数据的元数据信息,如数据类型、索引等,需要额外的处理来解决。
5.4、读 CSV 文件 —— read_csv
① 常用参数
pd.read_csv(filepath_or_buffer, # 文件名
sep=',', # 字段之间的分隔符,默认为逗号 ,
delimiter=None, # 作用同sep,若同时指定了 sep 和 delimiter,则以 delimiter 为准
header='infer', # 列名的行号。默认值为 'infer',表示 Pandas 将尝试自动推断列名
names=None, # 指定自定义的列名列表,如果 header=None,则通过 names 参数指定列名
index_col=None, # 指定哪一列作为索引列
usecols=None) # 指定要读取的列
② 例子
#编写person.csv文件
ID,Name,Age,City,Salary
1,Jack,28,Beijing,22000
2,Lida,32,Shanghai,19000
3,John,43,Shenzhen,12000
4,Helen,38,Hengshui,3500
import pandas as pd
from pandas import DataFrame
import numpy as np
# 直接读取,将会得到一个DataFrame对象
df1: DataFrame = pd.read_csv('./person.csv', # 读取的文件
header=0, # 将原来的列名删除
names=['i', 'n', 'a', 'c', 's'], # 自定义列名
dtype={'s': np.float64} # 重新指定字段的类型
)
print(df1)
print('-' * 30)
# 查看每一列的类型
print(df1.dtypes)
print('-' * 30)
# 选取一个字段做索引
df2 = pd.read_csv('./person.csv', # 文件名
index_col=0, ) # 选取第一列来做为索引,也可以写index_col=['ID']
print(df2)
print('-' * 30)
# 从csv文件的指定行开始读取
df3 = pd.read_csv('./person.csv', # 文件名
skiprows=2) # 跳过前两行再开始读取
print(df3)
#运行结果
i n a c s
0 1 Jack 28 Beijing 22000.0
1 2 Lida 32 Shanghai 19000.0
2 3 John 43 Shenzhen 12000.0
3 4 Helen 38 Hengshui 3500.0
------------------------------
i int64
n object
a int64
c object
s float64
dtype: object
------------------------------
Name Age City Salary
ID
1 Jack 28 Beijing 22000
2 Lida 32 Shanghai 19000
3 John 43 Shenzhen 12000
4 Helen 38 Hengshui 3500
------------------------------
2 Lida 32 Shanghai 19000
0 3 John 43 Shenzhen 12000
1 4 Helen 38 Hengshui 3500
5.5、写 CSV 文件 —— to_csv
① 常用参数
df.to_csv(path_or_buf, # 要写入的 CSV 文件的路径或者一个类文件对象
sep=",", # 指定字段之间的分隔符
na_rep="", # 用于替换缺失值的字符串
columns=None, # 要写入的列,可以是一个列名列表,指定写入的列顺序,也可以是一个字典,用于重命名列
header=True, # 是否写入列名
index=True, # 是否写入索引
mode="w", # 文件打开模式
encoding="utf-8", # 编码
line_terminator=r"\n", # 行终止符
date_format=None, # 日期格式
chunksize=None, # 写入时的分块大小
)
② 例子
import pandas as pd
data = {'Name': ['Smith', 'Parker'],
'ID': [101, 102],
'Language': ['Python', 'JavaScript']}
df = pd.DataFrame(data)
print(df)
print('-' * 30)
# 转换为csv数据
csv_data = df.to_csv(sep='|')
print(csv_data)
#运行结果
Name ID Language
0 Smith 101 Python
1 Parker 102 JavaScript
------------------------------
|Name|ID|Language
0|Smith|101|Python
1|Parker|102|JavaScript
5.6、写 Excel 文件 —— to_excel
安装依赖:pip install openpyxl
① 常用参数
df.to_excel(excel_writer, # 要写入的 Excel 文件的路径或者一个 ExcelWriter 对象
sheet_name='Sheet1', # 要写入的工作表的名称
na_rep='', # 替换缺失值的字符串
float_format=None, # 指定浮点数的格式
columns=None, # 要写入的列
header=True, # 指定是否写入列名
index=True, # 指定是否写入索引
index_label=None, # 指定索引列的名称
startrow=0, # 数据写入的起始行
startcol=0, # 数据写入的起始列
engine=None, # 使用的引擎
merge_cells=True, # 是否合并单元格
encoding=None, # 文件编码
inf_rep='inf', # 替换正负无穷值的字符串
verbose=True, # 是否显示写入过程中的详细信息
freeze_panes=None) # 指定要冻结的窗格
② 例子
import pandas as pd
from openpyxl.styles import Font, Alignment
from openpyxl.utils import get_column_letter
font = Font(name='Microsoft YaHei', size=11) # 字体样式
alignment = Alignment(horizontal='center', vertical='center') # 字体布局
# 创建DataFrame数据
df = pd.DataFrame({'name': ['编程帮', 'c语言中文网', '微学苑', '92python'],
'rank': [1, 2, 3, 4],
'language': ['PHP', 'C', 'PHP', 'Python'],
'url': ['www.bianchneg.com', 'c.bianchneg.net', 'www.weixueyuan.com', 'www.92python.com']})
# 创建ExcelWrite对象
writer = pd.ExcelWriter('./website.xlsx')
# 将数据传入
df.to_excel(writer)
# 修改xlxs中的样式
book = writer.book # excel表
sheet = book.active # 工作表
for row in sheet.iter_rows(min_row=1, min_col=1, max_row=sheet.max_row, max_col=sheet.max_column):
for cell in row:
cell.font = font # 将字体设置为微软雅黑 11号
cell.alignment = alignment # 居中
for i, col in enumerate(df.columns):
max_length = max(df[col].astype(str).map(len).max(), len(col)) # 计算每列的最大长度
sheet.column_dimensions[get_column_letter(i + 2)].width = max_length + 8 # 设置列宽
# 保存
writer.save()
5.7、读 Excel 文件 —— read_excel
① 常用参数
pd.read_excel(io, # excel文件的路径
sheet_name=0, # excel的工作表名
header=0, # 指定作为列名的行,不包含列明的话可以设定header=None,header=2表示将前两行作为多重索引
names=None, # 自定义列名
index_col=None, # 指定某一列的数据来作为行索引
usecols=None, # 要读取的列,默认为None表示要读取所有列
squeeze=False, # 是否将返回的 DataFrame 对象转换为 Series 对象
dtype=None, # 指定列的数据类型
engine=None, # 使用的解析引擎
converters=None, # 指定列的转换函数
true_values=None, # 指定布尔类型的字符串表示,默认为True
false_values=None, # 指定布尔类型的字符串表示,默认为False
skiprows=None, # 跳过指定的行数
nrows=None, # 要读取的行数
na_values=None, # 缺失值的字符串表示
parse_dates=False, # 是否将日期型数据解析为 datetime 对象
date_parser=None, # 解析日期型数据的函数
thousands=None, # 指定千位分隔符的字符
comment=None, # 指定注释的字符
skipfooter=0, # 要忽略末尾的某几行
convert_float=True) # 是否将整数类型的列转换为浮点型
② 例子
import pandas as pd
from pandas import DataFrame
# 读取Excel文件的所有数据
df1: DataFrame = pd.read_excel('./website.xlsx', # 路径
engine='openpyxl', # 解析引擎
index_col="name", # 用name这一列来作为索引
)
df1.columns = df1.columns.str.replace('Unnamed.*', 'col_label') # 将excel中的index的列名为空,转换成df之后空列名变成‘Unnameed:’,因此可以重命名一下
print(df1)
print('-' * 30)
# 读取Excel文件的部分数据+双重索引
df2: DataFrame = pd.read_excel('./website.xlsx', # 路径
engine='openpyxl', # 解析引擎
index_col=[1, 2], # 用两列来做索引(从0开始)
usecols=[1, 2, 3] # 选取excel中的三列(从0开始)
)
df2.columns = df2.columns.str.replace('Unnamed.*', 'col_label') # 将excel中的index的列名为空,转换成df之后空列名变成‘Unnameed:’,因此可以重命名一下
print(df2)
#运行结果
col_label rank language url
name
编程帮 0 1 PHP www.bianchneg.com
c语言中文网 1 2 C c.bianchneg.net
微学苑 2 3 PHP www.weixueyuan.com
92python 3 4 Python www.92python.com
------------------------------
name
rank language
1 PHP 编程帮
2 C c语言中文网
3 PHP 微学苑
4 Python 92python
6、数据表互联、分组聚合、数据透视
6.1、数据表互联
方法 | 描述 |
---|---|
merge | 用于根据一个或多个 键(列值) 将不同的 DataFrame 中的行连接起来 |
concat | 用于沿着指定轴将多个 DataFrame 连接起来 |
join | 用于根据 DataFrame 的 索引(行标签) 连接两个 DataFrame |
append | 用于将一个 DataFrame 添加到另一个 DataFrame 的末尾 |
import pandas as pd
# merge:联表(基于关键字/列)
df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': [1, 2, 3, 4]})
df2 = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value': [5, 6, 7, 8]})
merged_df = pd.merge(df1, df2, on='key', how='outer') # outer取并集
print(merged_df)
print('-' * 30)
# concat:沿指定轴合并(纵向/横向)
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']})
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'], 'B': ['B4', 'B5', 'B6', 'B7']})
concatenated_df1 = pd.concat([df1, df2], axis=0)
print(concatenated_df1)
print('-' * 30)
concatenated_df2 = pd.concat([df1, df2], axis=1)
print(concatenated_df2)
print('-' * 30)
# join:链表(基于index/行)
df1 = pd.DataFrame({'value1': [1, 2, 3, 4]}, index=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame({'value2': [5, 6, 7, 8]}, index=['B', 'D', 'E', 'F'])
joined_df = df1.join(df2, how='outer')
print(joined_df)
print('-' * 30)
# append:纵向合并
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']})
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'], 'B': ['B4', 'B5', 'B6', 'B7']})
appended_df = df1.append(df2)
print(appended_df)
key value_x value_y
0 A 1.0 NaN
1 B 2.0 5.0
2 C 3.0 NaN
3 D 4.0 6.0
4 E NaN 7.0
5 F NaN 8.0
------------------------------
A B
0 A0 B0
1 A1 B1
2 A2 B2
3 A3 B3
0 A4 B4
1 A5 B5
2 A6 B6
3 A7 B7
------------------------------
A B A B
0 A0 B0 A4 B4
1 A1 B1 A5 B5
2 A2 B2 A6 B6
3 A3 B3 A7 B7
------------------------------
value1 value2
A 1.0 NaN
B 2.0 5.0
C 3.0 NaN
D 4.0 6.0
E NaN 7.0
F NaN 8.0
------------------------------
A B
0 A0 B0
1 A1 B1
2 A2 B2
3 A3 B3
0 A4 B4
1 A5 B5
2 A6 B6
3 A7 B7
6.2、分组聚合
方式 | 描述 |
---|---|
groupby | 用于对数据进行分组 |
agg | 用于对分组后的数据进行聚合操作 |
import pandas as pd
# 创建示例 DataFrame
df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo'],
'B': ['one', 'one', 'two', 'two', 'one'],
'C': [1, 2, 3, 4, 5]})
# 按列 'A' 进行分组
grouped = df.groupby('A')
# 显示分组后的数据
for name, group in grouped:
print(name)
print(group)
print('-' * 30)
# 对分组后的数据进行聚合操作,计算每个分组的平均值和总和
aggregated = grouped.agg({'C': ['mean', 'sum']})
print(aggregated)
bar
A B C
1 bar one 2
3 bar two 4
------------------------------
foo
A B C
0 foo one 1
2 foo two 3
4 foo one 5
------------------------------
C
mean sum
A
bar 3 6
foo 3 9
6.3、数据透视
数据透视:一种数据分析技术,用于对大量数据进行汇总和分析,以便更好地理解数据之间的关系和趋势。数据透视可以将复杂的数据结构简化为易于理解的形式,提供对数据的直观认识和深入洞察
数据透视表(Pivot Table):数据透视技术的一种实现形式,它通过对数据进行汇总、分组和聚合操作,以多维度、多层次的方式展示数据,从而揭示数据之间的内在关系和规律
df.pivot_table(
index=None, # 用于分组的列或者列名,即将要在结果中作为行索引的列。
columns=None, # 用于分组的列或者列名,即将要在结果中作为列索引的列。
values=None, # 要聚合的列或者列名,即要在结果中显示的数据。
aggfunc="mean" # 指定对数据进行聚合计算的函数,例如 sum、mean、count 等,默认为 numpy.mean
)
import pandas as pd
# 创建示例 DataFrame
df = pd.DataFrame({'A': ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'],
'B': ['one', 'one', 'two', 'two', 'one', 'one'],
'C': [1, 2, 3, 4, 5, 6],
'D': [7, 8, 9, 10, 11, 12]})
print(df)
print('-' * 30)
# 使用 pivot_table 创建数据透视表
pivot = df.pivot_table(index='A', # 对A做分组,A作为数据透视表的索引
columns='B', # 对B做分组,B作为数据透视表的列
values='C', # 对C列做聚合
aggfunc='sum') # 统计每个分组,例如(bar,one),的C的总和
print(pivot)
A B C D
0 foo one 1 7
1 foo one 2 8
2 foo two 3 9
3 bar two 4 10
4 bar one 5 11
5 bar one 6 12
------------------------------
B one two
A
bar 11 4
foo 3 3
7、声明
本文参考了:
UQI-LIUWJ 的文章 pandas 知识点补充:绘图plot
小熊coder 的文章 Pandas教程(非常详细)
无忘,码民 的文章 python之pandas库,快速学习
感谢大牛们的分享和帮助!