介绍
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。
Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。
Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。
Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。
- Series: 类似于一维数组或列表,是由一组数据以及与之相关的数据标签(索引)构成。Series 可以看作是 DataFrame 中的一列,也可以是单独存在的一维数据结构。
- DataFrame: 类似于一个二维表格,它是 Pandas 中最重要的数据结构。DataFrame 可以看作是由多个 Series 按列排列构成的表格,它既有行索引也有列索引,因此可以方便地进行行列选择、过滤、合并等操作。
底层调用Numpy,Pandas给numpy的Ndarray添加行列名称,具体的计算还是调用Numpy来实现
MatPlotlib(静态绘图)
- Python数据可视化的三方库
- Pandas的数据可视化功能调用的是MatPlotLib
- Seaborn基于MatPlotLib
基于JS的绘图库(HTML页面展示)
- pyecharts
工具 | 功能特色 | 适用场景 |
---|---|---|
Excel | 图形界面,简单上手 | 人工分析、小规模数据 |
SQL | 高效读写,最终数据源 | 数据库查询和联表 |
Python+Pandas | 算法和分析部署核心 | 数据清晰,统计分析,可视化等 |
对比Series和DataFrame
特性 | Series | DataFrame |
---|---|---|
维度 | 一维 | 二维 |
索引 | 单索引 | 行索引+列名 |
数据存储 | 同质化数据类型 | 各列可不同数据类型 |
类比 | Excel单列 | 整张Excel工作表 |
创建方式 | pd.Series([1,2,3]) | pd.DataFrame({'col':[1,2,3]}) |
Series
A(Series Name) | |
---|---|
1(Series Index) | zhangsan(Series Values) |
Series这个数据类型,就可以看作是一个表格,类似excel、数据库那样
Series创建
pd.Series([1,2,3])
'''
0 1
1 2
2 3
dtype: int64
'''
可以输入第二个参数,自定义Series索引名称
s = pd.Series([1,2,3],index=['A','B','C'])
print(s)
'''
A 1
B 2
C 3
dtype: int64
'''
自定索引的数组长度,需要和SeriesValues数组的长度一致
为Series命名,添加第三个参数
s = pd.Series([1,2,3],name='numbers')
print(s)
'''
0 1
1 2
2 3
Name: numbers, dtype: int64
'''
通过字典创建
# 字典创建
s = pd.Series({
'a':1,'b':2,'c':3})
print(s)
'''
a 1
b 2
c 3
dtype: int64
'''
截取Series中的某些内容
- 传入原Series和指定内容的Series索引即可
s = pd.Series({
'a':1,'b':2,'c':3})
d = pd.Series(s,index=['a','c'])
print(d)
a = pd.Series([1,2,3],index=['A','B','C'])
e = pd.Series(a,index=['A','C'])
print(e)
'''
a 1
c 3
dtype: int64
A 1
C 3
dtype: int64
'''
Series属性
属性 | 说明 |
---|---|
index | Series的索引对象 |
values | Series的值 |
dType/dTypes | Series的元素类型 |
shape | Series的形状 |
ndim | Series的维度 |
size | Series的元素个数 |
name | Series的名称 |
loc[] | 显示索引,按标签索引或切片 |
iloc[] | 隐式索引,按位置索引或切片 |
at[] | 使用标签访问单个元素 |
iat[] | 使用位置访问单个元素 |
print(s.index)
print(s.values)
print(s.shape)
s.name = "获取名称"
print(s.ndim,s.size,s.name)
'''
Index(['a', 'b', 'c'], dtype='object')
[1 2 3]
(3,)
1 3 获取名称
'''
索引和获取元素
测试 | |
---|---|
A | 1 |
B | 2 |
C | 3 |
s = pd.Series({
'a':1,'b':2,'c':3},name='测试')
###
print(s.loc['a']) # 1
print(s.loc['a':'c'])
'''
a 1
b 2
c 3
Name: 测试, dtype: int64
'''
print(s.iloc[1]) # 隐式按照名称索引来查询
# 2
###
print(s.at['a']) # 1
print(s.iat[2])# 3
loc
和iloc
可以使用切片形式来获取多个元素而
at
和iat
无法使用切片形式
访问数据
使用loc或at系列也可以访问到数据
print(s[1]) # 不推荐
print(s['a'])# 不推荐
在Series中,也支持布尔索引
print(s[s<3])
'''
a 1
b 2
Name: 测试, dtype: int64
'''
获取从前或从后指定数量的数据
- 未指定数量,默认获取5条
print(s.head())
print(s.tail())
'''
a 1
b 2
c 3
d 4
e 5
Name: 测试, dtype: int64
c 3
d 4
e 5
f 6
g 7
Name: 测试, dtype: int64
'''
print(s.head(3))
print(s.tail(3))
'''
a 1
b 2
c 3
Name: 测试, dtype: int64
e 5
f 6
g 7
Name: 测试, dtype: int64
'''
Series常用方法
方法 | 说明 | 方法 | 说明 |
---|---|---|---|
head() | 查看前n行数据,默认5行 | max() | 最大值 |
tail() | 查看后n行数据,默认5行 | var() | 方差 |
isin() | 判断元素是否包含在参数集合中 | std() | 标准差 |
isna() | 判断是否未缺失值(如 NaN 或 None) | median() | 中位数 |
sum() | 求和,自动忽略缺失值 | mode() | 众数(可返回多个) |
mean() | 平均值 | quantile(a) | 分位数,a取0~1之间 |
min() | 最小值 | describe() | 常见统计信息 (count、mean、std、min、25%、50%、75%、max) |
value_counts() | 每个唯一值的出现次数 | sort_values() | 按值排序 |
count() | 非缺失值数量 | sort_index() | 按索引排序 |
nunique() | 唯一值个数(去重) | unique() | 获取去重后的值数组 |
drop_duplicates() | 去除重复项 | sample() | 随机抽样 |
replace() | 替换值 | keys() | 返回Series的索引对象 |
原始数据
import numpy as np
a = pd.Series({
'a':3,
'b':8,
'c':9,
'd':9,
'e':np.nan,
'f':None,
'g':10,
'h':11
},name='data')
print(a)
'''
a 3.0
b 8.0
c 9.0
d 9.0
e NaN
f NaN
g 10.0
h 11.0
Name: data, dtype: float64
'''
在Pandas中,np.nan
值也会被定义为 NaN
- None 值 也是
NaN
当Series中出现其他属性,默认为 float类型
查看所有的描述性信息
a.describe()
'''
count 6.000000
mean 8.333333
std 2.804758
min 3.000000
25% 8.250000
50% 9.000000
75% 9.750000
max 11.000000
Name: data, dtype: float64
'''
不论count()还是describe()中的count,都会舍去掉Series中的缺失值进行统计
print(a.count()) # 6
按个数获取 head(n) tail(n)
print(a.head(3))
print(a.tail(3))
'''
a 3.0
b 8.0
c 9.0
Name: data, dtype: float64
f NaN
g 10.0
h 11.0
Name: data, dtype: float64
'''
获取索引 keys() .index
- keys() 和 .index 这两个本质上无区别,获取的值的都是一致的
print(a.keys())
print(a.index)
'''
Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], dtype='object')
Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], dtype='object')
'''
判断是否为缺失值 isna()
print(a.isna())
'''
a False
b False
c False
d False
e True
f True
g False
h False
Name: data, dtype: bool
'''
检查元素是否在参数集合区间中 isin([])
- isin() 方法的参数为值的数组
判断依据就是Series值
a.isin([9,10])
'''
a False
b False
c True
d True
e False
f False
g True
h False
Name: data, dtype: bool
'''
print(a.isin(a[a>9]))
'''
a False
b False
c False
d False
e False
f False
g True
h True
Name: data, dtype: bool
'''
平均值、总和、标准差、方差、最大值、最小值、中位数...
与numpy使用一致
a['i'] = 11
print(a.mean()) # 平均值
print(a.sum()) # 总和
print(a.var()) # 标准差
print(a.std()) # 方差
print(a.max()) # 最大值
print(a.min()) # 最小值
print(a.median()) # 中位数
'''
8.714285714285714
61.0
7.571428571428573
2.751622897751175
11.0
3.0
9.0
'''
排序sort_index() sort_values()
- sort_index() 按照索引大小,从小到大排序
- sort_values() 按照元素值大小,从小到大排序
print(a.sort_index())
print(a.sort_values())
'''
a 3.0
b 8.0
c 9.0
d 9.0
e NaN
f NaN
g 10.0
h 11.0
i 11.0
Name: data, dtype: float64
a 3.0
b 8.0
c 9.0
d 9.0
g 10.0
h 11.0
i 11.0
e NaN
f NaN
Name: data, dtype: float64
'''
获取位数值 quantile()
quantile() 位数参数与numpy中的不一样
参数应是在 0 到 1 的区间,如 0.25,0.50,0.75这样
获取值的过程与 numpy 一致
a.quantile(0.25)
'''
np.float64(8.5)
'''
众数 mode()
获取出现次数最多的值
s.mode()
'''
0 9.0
1 11.0
Name: data, dtype: float64
'''
若Series中次数一样多,则返回多个值
统计元素值的个数 value_counts()
a.value_counts()
'''
data
9.0 2
11.0 2
3.0 1
8.0 1
10.0 1
Name: count, dtype: int64
'''
去重
drop_duplicates() 去除重复值,返回一个Series类型值
a.drop_duplicates()
'''
a 3.0
b 8.0
c 9.0
e NaN
g 10.0
h 11.0
Name: data, dtype: float64
'''
unique() 与 drop_duplicates() 去重后返回的值是一样的,但是类型不一样
- unique() 返回np.Array列表
a.unique()
# array([ 3., 8., 9., nan, 10., 11.])
nunique() 获取去重后的元素个数
a.nunique()
# 5
案例
学生成绩统计
创建一个包含10名学生数学成绩的Series,成绩范围在50-100之间。
计算平均分、最高分、最低分,并找出高于平均分的学生人数。
- 源码
np.random.seed(42)
scores = pd.Series(np.random.randint(50, 101, 10), index=['学生'+str(i) for i in range(1, 11)])
- 解题代码
m = scores.mean() # 平均分
print(m) # 73.7
max = scores.max() # 最高峰
min = scores.min() # 最低分
print(max,min) # 92 57
## 高于平均分的学生人数
print(scores[scores>m].count()) # 4
温度数据分析
给定某城市一周每天的最高温度Series,完成以下任务:
- 找出温度超过30度的天数
- 计算平均温度
- 将温度从高到低排序
- 找出温度变化最大的两天
- 源码
temperatures =pd.Series([28,31,29,32,30,27,33],index=['周一','周二','周三','周四','周五','周六','周日'])
print(temperatures)
- 解码
# 温度超30
print(temperatures[temperatures>30].count())# 3
# 平均温度
print(temperatures.mean())# 30.0
# 按温度从高到低排序
print(temperatures.sort_values(ascending=False))
'''
周日 33
周四 32
周二 31
周五 30
周三 29
周一 28
周六 27
dtype: int64
'''
## 温度变化最大的两天
print(temperatures.diff().abs().sort_values(ascending=False).index[:2].tolist())
# ['周日', '周二']
diff()
该方法获取Serise中第n个值
到第n+1个值
之间的差值,从第一个值
开始到最后一个值
结束temperatures.diff()
周一 NaN 周二 3.0 周三 -2.0 周四 3.0 周五 -2.0 周六 -3.0 周日 6.0 dtype: float64
由于第一个值的前面并没有值,所有差值为NaN
股票价格分析
给定某股票连续10个交易日的收盘价Series:
- 计算每日收益率(当日收盘价/前日收盘价-1)
- 找出收益率最高和最低的日期
- 计算波动率(收益率的标准差)
- 源码
prices=pd.Series([102.3, 103.5,105.1,104.8,106.2, 107.0,106.5,108.1,109.3,110.2],index=pd.date range('2023-01-01',periods=10))
- 解题:
# 计算每日收益率
# pct_change() 当前值/前一个值 - 1,从第一个元素开始到最后一个元素结束
pct = prices.pct_change() # pct:percent
print(pct)
'''
2023-01-01 NaN
2023-01-02 0.011730
2023-01-03 0.015459
2023-01-04 -0.002854
2023-01-05 0.013359
2023-01-06 0.007533
2023-01-07 -0.004673
2023-01-08 0.015023
2023-01-09 0.011101
2023-01-10 0.008234
Freq: D, dtype: float64
'''
### 收益最高日期
print(pct.idxmax()) # 2023-01-03 00:00:00
### 收益最低日期
print(pct.idxmin()) # 2023-01-07 00:00:00
### 计算波动率
print(pct.var()) # 5.4370328612877885e-05
pct_change()
与diff()
一致,只是,在此基础上将求差值变为求商,并且还-1
idxmax()
与在numpy中使用一致,将最大值的索引返回idxmin()
与在numpy中使用一致,将最小值的索引返回
销售数据分析
某产品过去12个月的销售量Series:
- 计算季度平均销量(每3个月为一个季度)
- 找出销量最高的月份
- 计算月环比增长率
- 找出连续增长超过2个月的月份
同比和环比增长的区别:
- 同比:是指
今年某个月与去年某个月
进行对比- 环比:是指
今年的某个月与该月的上一个月
进行对比
- 源码
sales=pd.Series([120,135,145,160,155,170,180,175,190,200,210,220],index=pd.date_range('2022-01-01',periods=12, freq='ME'))
print(sales)
- 解题:
## 季度(每三个月)平均销量
sales.resample('QS').mean()
'''
2022-01-01 133.333333
2022-04-01 161.666667
2022-07-01 181.666667
2022-10-01 210.000000
Freq: QS-JAN, dtype: float64
'''
resample(str)
重新采样str 是一种规则,并以此进行将以时间索引的Series分割
常见字符:
| 参数 | 说明 |
| --------- | ----------------------------- |
| QS | 季度(3个月) |
| xM | x为数字,M代表月 |
| xh | x为数字,h代表小时 |
| xmin / xT | x为数字,m代表分钟,T代表分钟 |
| xs | x为数字,s代表秒 |
## 销量最高的月份
print(str(sales.idxmax()).split('-')[1])
str()
强制转换split(str)
根据 str 字符 进行分割成数组
## 月环比增长率
print(sales.pct_change())
'''
2022-01-31 NaN
2022-02-28 0.125000
2022-03-31 0.074074
2022-04-30 0.103448
2022-05-31 -0.031250
2022-06-30 0.096774
2022-07-31 0.058824
2022-08-31 -0.027778
2022-09-30 0.085714
2022-10-31 0.052632
2022-11-30 0.050000
2022-12-31 0.047619
Freq: ME, dtype: float64
'''
## 找出连续增长超过2个月的月份
a = sales.pct_change()
b = a>0
b[b.rolling(3).sum()>=3].keys().tolist()
'''
[Timestamp('2022-04-30 00:00:00'),
Timestamp('2022-11-30 00:00:00'),
Timestamp('2022-12-31 00:00:00')]
'''
rolling(x)
依次从索引0处开始获取前x个元素。当不满足x个元素时,当前值为NaN当前试题的
b.rolling(3)
Rolling [window=3,center=False,axis=0,method=single]
我们看sales.pct_change() 该方法获得了增长率
''' 2022-01-31 NaN 2022-02-28 0.125000 2022-03-31 0.074074 2022-04-30 0.103448 2022-05-31 -0.031250 2022-06-30 0.096774 2022-07-31 0.058824 2022-08-31 -0.027778 2022-09-30 0.085714 2022-10-31 0.052632 2022-11-30 0.050000 2022-12-31 0.047619 Freq: ME, dtype: float64 '''
我们能够发现小于0的都属于负增长元素
满足条件的月份有哪些?4月、11月、12月
这三个月份满足本身月份前三个月都保持着增长的月份
将其进行分化,将小于0的都化作布尔值False反之是True
2022-01-31 False 2022-02-28 True 2022-03-31 True 2022-04-30 True 2022-05-31 False 2022-06-30 True 2022-07-31 True 2022-08-31 False 2022-09-30 True 2022-10-31 True 2022-11-30 True 2022-12-31 True Freq: ME, dtype: bool
再根据rolling(x),对每三个进行滚动计算;
.sum()
的作用,是将rolling后的每三个值进行了求和。若每三个值求和后>=3,就代表前三个月都保持着增长;2022-01-31 False 2022-02-28 False 2022-03-31 False 2022-04-30 True 2022-05-31 False 2022-06-30 False 2022-07-31 False 2022-08-31 False 2022-09-30 False 2022-10-31 False 2022-11-30 True 2022-12-31 True Freq: ME, dtype: bool
最后,再将符合True标准的元素取出并转为list
[Timestamp('2022-04-30 00:00:00'), Timestamp('2022-11-30 00:00:00'), Timestamp('2022-12-31 00:00:00')]
每小时销售数据分析
某商店每小时销售额Series:
- 按天重采样计算每日总销售额
- 计算每天营业时间(8:00-22:00)和非营业时间的销售额比例
- 找出销售额最高的3个小时
- 源码
np.random.seed(42)
hourly_sales = pd.Series(np.random.randint(0,100,24),index=pd.date_range('2025-01-01',periods=24, freq='h'))
print(hourly_sales)
- 解题:
## 按天重采样计算每日总销售额
print(hourly_sales.resample("D").sum())
'''
2025-01-01 1205
Freq: D, dtype: int32
'''
### 计算每天营业时间(8:00-22:00)和非营业时间的销售额比例
# 营业时间 - 三面三种方法求营业时间均可
hourly_sales.between_time('8:00','22:00')
hourly_sales['2025-01-01 08:00':'2025-01-01 22:00']
s = hourly_sales[(hourly_sales.index.hour >= 8) & (hourly_sales.index.hour <=22)]
# 非营业时间 - 下面两种方法求非营业时间均可
hourly_sales.drop(s.index)
hourly_sales[hourly_sales.index.hour<8 | hourly_sales.index.hour>22]
d = hourly_sales[~hourly_sales.isin(s)]
# 比例
rate = s.sum()/d.sum()
print(rate)
series.index
获得其索引,根据类型(DateTimeIndex)不同,可以获取不同的值series.index.hour
获取索引值的小时
还有方法
series.index.strftime('%H')
strftime()
指定的格式化字符串,可以为其获得指定的值- %H、%M、%S、%Y
~
波浪号,代表取反值
# 找出销售额最高的3个小时
hourly_sales.sort_values(ascending=False).head(3)
hourly_sales.nlargest(3)
'''
2025-01-01 11:00:00 99
2025-01-01 01:00:00 92
2025-01-01 10:00:00 87
dtype: int32
'''
nlargest(x)
取最大的x个值
🎶😘数据分析章节回顾
(numpy)Python做数据处理必备框架!(一):认识numpy;从概念层面开始学习ndarray数组:形状、数组转置、数值范围、矩阵...
(numpy)Python做数据处理必备框架!(二):ndarray切片的使用与运算;常见的ndarray函数:平方根、正余弦、自然对数、指数、幂等运算;统计函数:方差、均值、极差;比较函数...
💕👉博客专栏
- 新时代语言Python专栏:基础、Anaconda、数据分析三框架(numpy、pandas、matpltlib)
- Golang专栏-包含基础、Gin、Goam等知识
- 云原生专栏-包含k8s、docker等知识
- 从0开始学习云计算-华为HCIP证书
- JUC专栏-带你快速领悟JUC的知识!
- JVM专栏-深入Java虚拟机,理解JVM的原理
- 基于Java研究 数据结构与算法-包含贪心算法、加权图、最短路径算法等知识
- Docker专栏-上手热门容器技术Docker
- SpringBoot专栏-学习SpringBoot快速开发后端
- 项目管理工具的学习-设计技术:Maven、Git、Gradle等相关管理工具
- JavaSE-全面了解Java基础
- JS专栏-使用JS作的一部分实例~
- 使用CSS所作的一部分案例