文章目录
- 聚合和分组的概念
-
- 一、概念解释
-
- [1. 分组(Grouping)](#1. 分组(Grouping))
- [2. 聚合(Aggregation)](#2. 聚合(Aggregation))
- 数据的分组与聚合
- 数据的排序和排名
- [Pandas 数据的排序和排名详解](#Pandas 数据的排序和排名详解)
-
- 一、数据排序
- 二、数据排名
-
- [1. rank() - 排名方法](#1. rank() - 排名方法)
- [2. rank()的5种排名方法详解](#2. rank()的5种排名方法详解)
-
- [(1) average(默认)- 平均排名](#(1) average(默认)- 平均排名)
- [(2) min - 最小排名](#(2) min - 最小排名)
- [(3) max - 最大排名](#(3) max - 最大排名)
- [(4) first - 按出现顺序](#(4) first - 按出现顺序)
- [(5) dense - 密集排名](#(5) dense - 密集排名)
- [3. 排名方法对比](#3. 排名方法对比)
- 三、实际应用案例
- 四、总结
- 时间序列分析
-
- 一、时间序列分析的概念与意义
-
- [1. 什么是时间序列分析?](#1. 什么是时间序列分析?)
- [2. 时间序列分析的重要性](#2. 时间序列分析的重要性)
- 二、Pandas时间序列处理的核心概念
-
- [1. Pandas时间类型体系](#1. Pandas时间类型体系)
- [2. 时间序列数据的基本结构](#2. 时间序列数据的基本结构)
- [3. 时间频率与偏移量](#3. 时间频率与偏移量)
- 三、Pandas时间序列处理的关键操作
-
- [1. 设置时间索引](#1. 设置时间索引)
- [2. 重采样(Resampling)](#2. 重采样(Resampling))
- [3. 滑动窗口分析](#3. 滑动窗口分析)
- [4. 缺失值处理](#4. 缺失值处理)
- [5. 时间特征提取](#5. 时间特征提取)
- 实际案例
- [四、 什么是移动平均](#四、 什么是移动平均)
- 使用Pandas进行移动平均
- 一个更简单的例子
聚合和分组的概念
一、概念解释
1. 分组(Grouping)
分组是将数据按照特定标准划分为多个组的操作。就像把一堆球按照颜色分类,红色球放一堆,蓝色球放一堆。
分组依据可以是:
- 单个列(如"性别"、"地区")
- 多个列组合(如"地区+性别")
- Series对象
- 字典(将列名映射到自定义分组)
- 函数(对索引应用函数生成分组依据)
分组操作特点:
- 不进行实际计算,只是将数据组织成组
- 返回一个GroupBy对象(表示分组的中间状态)
- 通过
groupby()方法实现
2. 聚合(Aggregation)
聚合是对每个组进行统计计算的操作。就像对每种颜色的球堆计算总数、平均重量等。
聚合操作特点:
- 对每个组应用统计函数
- 返回每个组的统计结果
- 常用聚合函数:
sum()、mean()、count()、min()、max()等
数据的分组与聚合
分组与聚合的流程
分组与聚合遵循"拆分-应用-合并"(Split-Apply-Combine)原则:
- 拆分(Split):将数据集按照指定标准划分为多个组
- 应用(Apply):将聚合函数应用到每个分组
- 合并(Combine):将计算结果整合到结果对象中
二、实例详解
实例1:基本分组与聚合
假设我们有一个销售数据集:
| 产品类别 | 销售额 |
|---|---|
| A | 100 |
| B | 200 |
| A | 300 |
| B | 400 |
| A | 500 |
| B | 600 |
分组操作:按"产品类别"分组
python
import pandas as pd
data = {
'产品类别': ['A', 'B', 'A', 'B', 'A', 'B'],
'销售额': [100, 200, 300, 400, 500, 600]
}
df = pd.DataFrame(data)
# 按产品类别分组
grouped = df.groupby('产品类别')
聚合操作:计算每个产品类别的平均销售额
python
# 计算平均销售额
average_sales = grouped['销售额'].mean()
print(average_sales)
输出:
产品类别
A 300.0
B 400.0
Name: 销售额, dtype: float64
解释:
- 产品类别A的销售额:100, 300, 500 → 平均值 = 300
- 产品类别B的销售额:200, 400, 600 → 平均值 = 400
实例2:多列分组与多聚合函数
继续使用上面的数据,但这次我们按两个维度分组,并应用多个聚合函数:
python
# 创建更复杂的数据集
data = {
'产品类别': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B'],
'销售月份': ['Jan', 'Jan', 'Feb', 'Feb', 'Jan', 'Jan', 'Feb', 'Feb'],
'销售额': [100, 200, 300, 400, 500, 600, 700, 800]
}
df = pd.DataFrame(data)
# 按产品类别和销售月份分组
grouped = df.groupby(['产品类别', '销售月份'])
# 应用多个聚合函数
result = grouped['销售额'].agg(['sum', 'mean', 'count'])
print(result)
输出:
sum mean count
产品类别 销售月份
A Jan 600 300 2
Feb 700 350 2
B Jan 800 400 2
Feb 800 400 2
解释:
- 产品类别A在1月的销售额:100 + 500 = 600,平均值300,共2行
- 产品类别A在2月的销售额:300 + 700 = 1000?(注意:上面示例数据中2月A的销售额是300和700,总和应为1000)
- 产品类别B在1月的销售额:200 + 600 = 800,平均值400,共2行
- 产品类别B在2月的销售额:400 + 800 = 1200,平均值600,共2行
实例3:使用agg()进行复杂聚合
python
# 定义一个计算极差的函数
def range_value(x):
return x.max() - x.min()
# 按产品类别分组,应用多个聚合函数
result = df.groupby('产品类别')['销售额'].agg([
('总销售额', 'sum'),
('平均销售额', 'mean'),
('销售额极差', range_value),
('产品数量', 'count')
])
print(result)
输出:
总销售额 平均销售额 销售额极差 产品数量
产品类别
A 1600 400.0 600 4
B 2000 500.0 600 4
解释:
- 产品类别A的总销售额:100+300+500+700 = 1600
- 产品类别A的平均销售额:400
- 产品类别A的销售额极差:700-100 = 600
- 产品类别A共有4个销售记录
数据的排序和排名
Pandas 数据的排序和排名详解
一、数据排序
排序是数据分析中最基础的操作之一,用于将数据按特定顺序排列。Pandas提供了两种主要的排序方法:sort_values()和sort_index()。
1. sort_values() - 按值排序
这是最常用的排序方法,用于根据列的值进行排序。
基本用法
python
# 按单列升序排序
df_sorted = df.sort_values('列名')
# 按单列降序排序
df_sorted_desc = df.sort_values('列名', ascending=False)
多列排序
python
# 按多列排序(先按A列升序,再按B列降序)
df_sorted_multi = df.sort_values(by=['A', 'B'], ascending=[True, False])
示例:
python
import pandas as pd
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 40],
'成绩': [85, 90, 75, 95]
}
df = pd.DataFrame(data)
# 按成绩降序排序
sorted_df = df.sort_values('成绩', ascending=False)
print(sorted_df)
输出:
姓名 年龄 成绩
1 李四 30 90
3 赵六 40 95
0 张三 25 85
2 王五 35 75
2. sort_index() - 按索引排序
用于根据索引标签进行排序。
基本用法
python
# 按行索引升序排序
df_sorted = df.sort_index()
# 按行索引降序排序
df_sorted_desc = df.sort_index(ascending=False)
# 按列索引排序
df_sorted_cols = df.sort_index(axis=1)
示例:
python
# 创建带自定义索引的DataFrame
df = pd.DataFrame(
{'A': [3, 1, 2], 'B': [5, 2, 4]},
index=['c', 'a', 'b']
)
# 按行索引升序排序
print(df.sort_index())
# 按行索引降序排序
print(df.sort_index(ascending=False))
# 按列索引排序
print(df.sort_index(axis=1))
输出:
A B
a 1 2
b 2 4
c 3 5
A B
c 3 5
b 2 4
a 1 2
B A
c 5 3
a 2 1
b 4 2
二、数据排名
排名用于为数据分配排名(从1开始,一直到有效数据的数量),与排序密切相关。
1. rank() - 排名方法
python
# 为指定列进行排名
df['排名'] = df['列名'].rank()
rank()的常用参数
| 参数 | 说明 | 默认值 |
|---|---|---|
method |
排名方法 | 'average' |
ascending |
是否升序排名 | True |
na_option |
NA值处理方式 | 'keep' |
2. rank()的5种排名方法详解
(1) average(默认)- 平均排名
相同值取平均排名
示例:
python
data = {'姓名': ['张三', '李四', '王五', '赵六'], '英语': [90, 83, 70, 83]}
df = pd.DataFrame(data)
df['平均排名'] = df['英语'].rank(method='average', ascending=False)
print(df)
输出:
姓名 英语 平均排名
0 张三 90 1.0
1 李四 83 2.5
2 王五 70 4.0
3 赵六 83 2.5
解释:
- 90分排名第1
- 两个83分并列,它们应该占据第2和第3名,所以取平均值(2+3)/2=2.5
- 70分排名第4
(2) min - 最小排名
相同值取最小排名
示例:
python
df['最小排名'] = df['英语'].rank(method='min', ascending=False)
print(df)
输出:
姓名 英语 平均排名 最小排名
0 张三 90 1.0 1
1 李四 83 2.5 2
2 王五 70 4.0 4
3 赵六 83 2.5 2
解释:
- 90分排名第1
- 两个83分都取较小的排名值2
- 70分排名第4
(3) max - 最大排名
相同值取最大排名
示例:
python
df['最大排名'] = df['英语'].rank(method='max', ascending=False)
print(df)
输出:
姓名 英语 平均排名 最小排名 最大排名
0 张三 90 1.0 1 1
1 李四 83 2.5 2 3
2 王五 70 4.0 4 4
3 赵六 83 2.5 2 3
解释:
- 90分排名第1
- 两个83分都取较大的排名值3
- 70分排名第4
(4) first - 按出现顺序
按数据在原始数据中的出现顺序决定排名
示例:
python
df['顺序排名'] = df['英语'].rank(method='first', ascending=False)
print(df)
输出:
姓名 英语 平均排名 最小排名 最大排名 顺序排名
0 张三 90 1.0 1 1 1
1 李四 83 2.5 2 3 2
2 王五 70 4.0 4 4 4
3 赵六 83 2.5 2 3 3
解释:
- 90分排名第1
- 先出现的李四(83分)排名2
- 后出现的赵六(83分)排名3
- 70分排名第4
(5) dense - 密集排名
相同值取相同排名,不跳过后续排名
示例:
python
df['密集排名'] = df['英语'].rank(method='dense', ascending=False)
print(df)
输出:
姓名 英语 平均排名 最小排名 最大排名 顺序排名 密集排名
0 张三 90 1.0 1 1 1 1
1 李四 83 2.5 2 3 2 2
2 王五 70 4.0 4 4 4 3
3 赵六 83 2.5 2 3 3 2
解释:
- 90分排名第1
- 两个83分都排名2
- 70分排名3(不跳过数字)
3. 排名方法对比
| 姓名 | 英语 | average | min | max | first | dense |
|---|---|---|---|---|---|---|
| 张三 | 90 | 1 | 1 | 1 | 1 | 1 |
| 李四 | 83 | 2.5 | 2 | 3 | 2 | 2 |
| 赵六 | 83 | 2.5 | 2 | 3 | 3 | 2 |
| 王五 | 70 | 4 | 4 | 4 | 4 | 3 |
三、实际应用案例
案例1:销售数据分析
python
import pandas as pd
# 创建销售数据
sales_data = {
'产品': ['A', 'B', 'C', 'D', 'E'],
'销售额': [12000, 15000, 10000, 18000, 13000]
}
sales_df = pd.DataFrame(sales_data)
# 按销售额降序排序
sales_sorted = sales_df.sort_values('销售额', ascending=False)
# 计算销售额排名(使用平均排名)
sales_sorted['排名'] = sales_sorted['销售额'].rank(method='average', ascending=False)
print("销售数据排序与排名:")
print(sales_sorted)
输出:
产品 销售额 排名
3 D 18000 1.0
1 B 15000 2.0
4 E 13000 3.0
0 A 12000 4.0
2 C 10000 5.0
案例2:学生成绩分析
python
import pandas as pd
# 创建学生数据
students = {
'姓名': ['张三', '李四', '王五', '赵六', '钱七', '孙八'],
'语文': [85, 90, 75, 80, 88, 92],
'数学': [90, 85, 88, 92, 80, 85]
}
df = pd.DataFrame(students)
# 按语文成绩降序排序
df_sorted = df.sort_values('语文', ascending=False)
# 计算语文成绩排名
df_sorted['语文排名'] = df_sorted['语文'].rank(method='min', ascending=False)
# 按数学成绩排序并计算排名
df_sorted['数学排名'] = df_sorted['数学'].rank(method='dense', ascending=False)
print("学生语文成绩排名:")
print(df_sorted)
输出:
姓名 语文 数学 语文排名 数学排名
1 李四 90 85 1 3
5 孙八 92 85 1 3
4 钱七 88 80 3 5
0 张三 85 90 4 1
3 赵六 80 92 5 2
2 王五 75 88 6 4
四、总结
排序与排名关键点
| 操作 | 方法 | 主要用途 | 常用参数 |
|---|---|---|---|
| 按值排序 | sort_values() |
根据列的值进行排序 | by, ascending, inplace |
| 按索引排序 | sort_index() |
根据索引标签进行排序 | axis, ascending, inplace |
| 排名 | rank() |
为数据分配排名 | method, ascending, na_option |
结合使用,例如先排序再进行排名,或按特定条件进行多级排序和排名。
时间序列分析
一、时间序列分析的概念与意义
1. 什么是时间序列分析?
时间序列分析是指对按时间顺序排列的数据点进行分析,以发现数据随时间变化的模式、趋势和规律。时间序列数据具有以下核心特征:
- 时间依赖性:当前观测值与历史观测值存在关联
- 趋势性:数据随时间呈现上升或下降的长期趋势
- 季节性:数据在固定周期内重复出现的模式(如月度、季度)
- 周期性:非固定周期的波动(如经济周期)
- 随机性:无法预测的随机波动
时间序列数据示例:股票价格、每日气温、网站日访问量、每日销售额、设备传感器读数等
2. 时间序列分析的重要性
时间序列分析在多个领域具有重要价值:
- 金融领域:股票价格预测、风险评估
- 物联网:设备健康监测、故障预测
- 商业智能:销售趋势分析、库存优化
- 气象学:天气预报、气候研究
- 制造业:生产过程监控、质量控制
二、Pandas时间序列处理的核心概念
1. Pandas时间类型体系
Pandas构建了完整的时间类型体系,使时间序列处理更加高效:
| 类型 | 说明 | 示例 |
|---|---|---|
| Timestamp | 表示特定时间点(如"2023-01-01 12:00:00") | pd.Timestamp('2023-01-01 12:00:00') |
| Period | 表示时间区间(如"2023年1月") | pd.Period('2023-01', freq='M') |
| Timedelta | 表示两个时间点之间的差值 | pd.Timedelta(days=5, hours=3) |
| DatetimeIndex | 由Timestamp组成的索引,用于时间序列数据 | pd.DatetimeIndex(['2023-01-01', '2023-01-02']) |
2. 时间序列数据的基本结构
Pandas使用DatetimeIndex作为时间序列数据的核心索引类型,使数据按时间标签高效检索和对齐。
创建时间索引的常用方法:
python
import pandas as pd
# 生成连续时间索引
dates = pd.date_range(start='2023-01-01', periods=10, freq='D')
print(dates)
# 输出: DatetimeIndex(['2023-01-01', '2023-01-02', ..., '2023-01-10'], dtype='datetime64[ns]', freq='D')
3. 时间频率与偏移量
Pandas支持多种时间频率别名,用于定义时间序列的间隔:
| 频率别名 | 含义 | 示例 |
|---|---|---|
D |
每日 | pd.date_range(start='2023-01-01', periods=10, freq='D') |
H |
每小时 | pd.date_range(start='2023-01-01', periods=24, freq='H') |
B |
工作日(跳过周末) | pd.date_range(start='2023-01-01', periods=10, freq='B') |
M |
每月最后一天 | pd.date_range(start='2023-01-01', periods=12, freq='M') |
W |
每周 | pd.date_range(start='2023-01-01', periods=52, freq='W') |
Q |
每季度 | pd.date_range(start='2023-01-01', periods=4, freq='Q') |
三、Pandas时间序列处理的关键操作
1. 设置时间索引
将普通列转换为时间索引:
python
# 读取含日期字段的数据集
df = pd.read_csv('data.csv')
# 将日期列转换为标准时间格式
df['date'] = pd.to_datetime(df['date'])
# 将日期列设为索引
df = df.set_index('date')
# 或者直接在读取时设置索引
df = pd.read_csv('data.csv', parse_dates=['date'], index_col='date')
2. 重采样(Resampling)
重采样是时间序列分析中最常用的操作之一,用于调整数据的时间频率:
降采样(高频转低频):
python
# 将每日数据转换为月度数据(求和)
monthly_data = df.resample('M').sum()
# 将每日数据转换为季度数据(求平均)
quarterly_data = df.resample('Q').mean()
升采样(低频转高频):
python
# 将月度数据转换为每日数据(前向填充)
daily_data = df.resample('D').ffill()
# 将月度数据转换为每日数据(线性插值)
daily_data = df.resample('D').interpolate('linear')
重采样示例:
python
# 创建示例数据
dates = pd.date_range(start='2023-01-01', periods=30, freq='D')
data = pd.Series(range(30), index=dates)
# 降采样为每周(求和)
weekly = data.resample('W').sum()
print("每周总和:\n", weekly)
# 升采样为每小时
hourly = data.resample('H').ffill()
print("\n每小时数据:\n", hourly)
3. 滑动窗口分析
滑动窗口分析能揭示时间序列数据的短期趋势和模式,是异常检测和趋势分析的有力工具。
基本用法:
python
# 计算7天移动平均
df['7_day_ma'] = df['value'].rolling(window=7).mean()
# 计算30天移动标准差
df['30_day_std'] = df['value'].rolling(window=30).std()
# 计算30天移动相关系数
df['corr'] = df['value'].rolling(window=30).corr(df['other_value'])
高级滑动窗口应用:
python
# 计算10分钟窗口的振动能量(RMS)
df['vibration_rms'] = df['acceleration'].rolling('10T').apply(lambda x: np.sqrt(np.mean(x**2)))
# 计算24小时移动平均
df['24h_ma'] = df['value'].rolling('24H').mean()
4. 缺失值处理
时间序列数据中缺失值处理需要特殊技巧:
python
# 前向填充
df_filled = df.fillna(method='ffill')
# 后向填充
df_filled = df.fillna(method='bfill')
# 线性插值
df_filled = df.interpolate(method='linear')
# 用特定值填充
df_filled = df.fillna(0)
5. 时间特征提取
从时间戳中提取有用特征:
python
# 提取年份、月份、星期几等
df['year'] = df.index.year
df['month'] = df.index.month
df['day'] = df.index.day
df['weekday'] = df.index.weekday
df['is_weekend'] = df.index.weekday >= 5
# 提取季度
df['quarter'] = df.index.quarter
# 提取是否为月末
df['is_month_end'] = df.index.is_month_end
实际案例
四、 什么是移动平均
移动平均是一种简单但有效的时间序列平滑技术,通过计算固定窗口内数据的平均值来减少数据波动,帮助我们更清晰地看到数据的整体趋势。
使用Pandas进行移动平均
在Pandas中,我们可以使用rolling()方法配合mean()函数来计算移动平均值。
基本步骤
- 确保你的数据有时间索引
- 使用
rolling(window_size)指定窗口大小 - 调用
mean()计算平均值
简单示例
python
import pandas as pd
import numpy as np
# 创建示例时间序列数据
dates = pd.date_range(start='2023-01-01', periods=10, freq='D')
values = [10, 15, 20, 25, 30, 35, 40, 45, 50, 55]
df = pd.DataFrame({'value': values}, index=dates)
# 计算3天移动平均
df['moving_avg'] = df['value'].rolling(window=3).mean()
print(df)
输出结果:
value moving_avg
2023-01-01 10 NaN
2023-01-02 15 NaN
2023-01-03 20 15.0
2023-01-04 25 20.0
2023-01-05 30 25.0
2023-01-06 35 30.0
2023-01-07 40 35.0
2023-01-08 45 40.0
2023-01-09 50 45.0
2023-01-10 55 50.0
解释
- 前2个值显示为
NaN,因为窗口大小为3,前2个数据点无法形成完整的窗口 - 从第3个数据点开始,每个移动平均值都是当前点和前2个点的平均值
- 2023-01-03: (10 + 15 + 20) / 3 = 15
- 2023-01-04: (15 + 20 + 25) / 3 = 20
- 以此类推
为什么使用移动平均
- 平滑数据:减少随机波动,使趋势更明显
- 识别模式:更容易看出数据的长期趋势
- 预测基础:为更复杂的预测模型提供基础
常见窗口大小选择
- 短期分析:窗口大小=5-7天(如股票交易)
- 中期分析:窗口大小=15-30天(如销售趋势)
- 长期分析:窗口大小=90-365天(如年度趋势)
注意事项
- 窗口大小会影响结果:窗口越大,平滑效果越明显,但可能丢失短期波动
- 前几个数据点会显示为
NaN,因为没有足够的数据计算平均值 - 可以使用
min_periods参数控制最少需要多少个数据点才能计算平均值
python
# 设置min_periods参数,让前几个数据点也能计算
df['moving_avg'] = df['value'].rolling(window=3, min_periods=1).mean()
一个更简单的例子
python
import pandas as pd
# 创建简单数据
data = [10, 15, 20, 25, 30]
df = pd.DataFrame(data, columns=['value'])
# 计算3天移动平均
df['moving_avg'] = df['value'].rolling(window=3).mean()
print(df)
输出:
value moving_avg
0 10 NaN
1 15 NaN
2 20 15.0
3 25 20.0
4 30 25.0