(Pandas)Python做数据处理必选框架之一!(一):介绍Pandas中的两个数据结构;刨析Series:如何访问数据;数据去重、取众数、总和、标准差、方差、平均值等;判断缺失值、获取索引...

本文涉及的产品
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
模型训练 PAI-DLC,100CU*H 3个月
交互式建模 PAI-DSW,每月250计算时 3个月
简介: Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。

介绍

Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。

Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。

Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。

Pandas 主要引入了两种新的数据结构:SeriesDataFrame

  • 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 算法和分析部署核心 数据清晰,统计分析,可视化等

Pandas功能架构.png

对比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

lociloc 可以使用切片形式来获取多个元素

atiat 无法使用切片形式

访问数据

使用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,完成以下任务:

  1. 找出温度超过30度的天数
  2. 计算平均温度
  3. 将温度从高到低排序
  4. 找出温度变化最大的两天
  • 源码
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. 计算每日收益率(当日收盘价/前日收盘价-1)
  2. 找出收益率最高和最低的日期
  3. 计算波动率(收益率的标准差)
  • 源码
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:

  1. 计算季度平均销量(每3个月为一个季度)
  2. 找出销量最高的月份
  3. 计算月环比增长率
  4. 找出连续增长超过2个月的月份

同比和环比增长的区别:

  1. 同比:是指今年某个月与去年某个月进行对比
  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]
    
  1. 我们看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月

    这三个月份满足本身月份前三个月都保持着增长的月份

  2. 将其进行分化,将小于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
    
  3. 再根据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
    
  4. 最后,再将符合True标准的元素取出并转为list

    [Timestamp('2022-04-30 00:00:00'),
     Timestamp('2022-11-30 00:00:00'),
     Timestamp('2022-12-31 00:00:00')]
    

每小时销售数据分析

某商店每小时销售额Series:

  1. 按天重采样计算每日总销售额
  2. 计算每天营业时间(8:00-22:00)和非营业时间的销售额比例
  3. 找出销售额最高的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函数:平方根、正余弦、自然对数、指数、幂等运算;统计函数:方差、均值、极差;比较函数...

💕👉博客专栏

目录
相关文章
|
11天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
10天前
|
存储 人工智能 搜索推荐
终身学习型智能体
当前人工智能前沿研究的一个重要方向:构建能够自主学习、调用工具、积累经验的小型智能体(Agent)。 我们可以称这种系统为“终身学习型智能体”或“自适应认知代理”。它的设计理念就是: 不靠庞大的内置知识取胜,而是依靠高效的推理能力 + 动态获取知识的能力 + 经验积累机制。
356 131
|
10天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
443 131
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
4天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
206 138
|
10天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
405 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
4天前
|
存储 JSON 安全
加密和解密函数的具体实现代码
加密和解密函数的具体实现代码
204 136
|
22天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1363 8
|
9天前
|
监控 JavaScript Java
基于大模型技术的反欺诈知识问答系统
随着互联网与金融科技发展,网络欺诈频发,构建高效反欺诈平台成为迫切需求。本文基于Java、Vue.js、Spring Boot与MySQL技术,设计实现集欺诈识别、宣传教育、用户互动于一体的反欺诈系统,提升公众防范意识,助力企业合规与用户权益保护。

热门文章

最新文章