Pandas 描述分析和分组分析学习文档
📚 目录
1. 环境配置与数据导入
1.1 必要模块导入
📌 核心概念
在进行数据分析前,需要导入必要的Python库来支持数据处理、数值计算和可视化功能。
📝 代码示例
python
# 导入数值计算库
import numpy as np
# 导入数据分析库
import pandas as pd
# 导入绘图库
import matplotlib.pyplot as plt
# 导入统计可视化库(可选)
import seaborn as sns
# 忽略警告信息(可选)
import warnings
warnings.filterwarnings('ignore')
💡 知识点:各库的作用
- NumPy: 提供高性能的数值计算和数组操作
- Pandas: 提供数据结构(DataFrame、Series)和数据分析工具
- Matplotlib: Python的基础绘图库,用于创建各种静态图表
- Seaborn: 基于Matplotlib的高级可视化库,提供更美观的统计图表
1.2 中文显示配置
📌 核心概念
Matplotlib默认不支持中文显示,需要配置字体才能正常显示中文标签和标题。
📝 代码示例
python
# 设置中文字体为黑体(SimHei)
plt.rcParams['font.sans-serif'] = 'SimHei'
# 正常显示负号(解决负号显示为方块的问题)
plt.rcParams['axes.unicode_minus'] = False
⚠️ 注意事项
- 必须在绘图前设置字体,否则中文会显示为方块
SimHei(黑体)是Windows系统常用的中文字体- Mac系统可使用
'Arial Unicode MS'或'PingFang SC' - Linux系统可使用
'WenQuanYi Micro Hei'
1.3 数据读取
🔧 函数:pd.read_csv()
📊 参数说明
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| filepath | str | 文件路径 | 必填 |
| encoding | str | 文件编码格式 | 'utf-8' |
| sep | str | 分隔符 | ',' |
| header | int/None | 表头行号 | 0 |
| index_col | int/str/list | 用作索引的列 | None |
📝 代码示例
python
# 读取CSV文件(GBK编码)
data = pd.read_csv('HR.csv', encoding='gbk')
# 读取CSV文件(UTF-8编码)
data = pd.read_csv('data.csv', encoding='utf-8')
# 指定第一列为索引
data = pd.read_csv('data.csv', index_col=0)
⚠️ 常见编码问题
- GBK: 中文Windows系统常用编码
- UTF-8: 国际通用编码,推荐使用
- GB2312: 简体中文编码
- 如果出现乱码,尝试更换encoding参数
💎 最佳实践
python
✅ 推荐:使用相对路径
data = pd.read_csv('./data/HR.csv', encoding='gbk')
❌ 避免:使用绝对路径(降低代码可移植性)
data = pd.read_csv('C:/Users/Desktop/HR.csv', encoding='gbk')
2. 描述性统计分析
📌 核心概念
描述性统计分析是数据分析的第一步,通过统计指标和可视化方法快速了解数据的整体特征、分布情况和潜在问题。
2.1 数据完整性分析
💡 知识点:数据完整性检查
在分析数据前,首先要了解数据的基本信息,包括数据类型、缺失值情况、内存占用等。
🔧 函数:DataFrame.info()
📝 代码示例
python
# 查看数据基本信息
data.info()
# 输出示例:
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 15000 entries, 0 to 14999
# Data columns (total 10 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 员工满意度 15000 non-null float64
# 1 考核评分 15000 non-null float64
# 2 项目数量 15000 non-null int64
# ...
📊 info()输出信息解读
| 信息项 | 含义 | 用途 |
|---|---|---|
| RangeIndex | 索引范围 | 了解数据行数 |
| Non-Null Count | 非空值数量 | 检测缺失值 |
| Dtype | 数据类型 | 区分数值型/类别型 |
| memory usage | 内存占用 | 评估数据规模 |
💎 最佳实践
- 数据分析的第一步必须执行
info() - 检查Non-Null Count是否等于总行数,判断是否有缺失值
- 根据Dtype区分数值型和类别型数据,采用不同的分析方法
2.2 数值型数据描述分析
📌 核心概念
数值型数据(连续型数据)通过统计量和分布图来描述其集中趋势、离散程度和分布形态。
🔧 函数:DataFrame.describe()
💡 知识点:8个统计量
describe()默认计算数值型列的8个统计指标,全面描述数据分布特征。
📊 统计量说明
| 统计量 | 英文 | 含义 | 计算方法 |
|---|---|---|---|
| count | 计数 | 非空值数量 | 统计非NaN值个数 |
| mean | 均值 | 平均值 | sum(x) / count(x) |
| std | 标准差 | 离散程度 | 衡量数据波动性 |
| min | 最小值 | 最小观测值 | 数据中的最小数 |
| 25% | 下四分位数 | Q1分位点 | 25%的数据小于此值 |
| 50% | 中位数 | Q2分位点 | 50%的数据小于此值 |
| 75% | 上四分位数 | Q3分位点 | 75%的数据小于此值 |
| max | 最大值 | 最大观测值 | 数据中的最大数 |
📝 代码示例
python
# 获取数值型数据的描述统计
data.describe()
# 输出示例:
# 员工满意度 考核评分 每月在公司工作时间
# count 15000.0 15000.0 15000.0
# mean 0.61 0.72 201.05
# std 0.25 0.18 49.94
# min 0.09 0.36 96.00
# 25% 0.44 0.56 156.00
# 50% 0.64 0.72 200.00
# 75% 0.82 0.87 245.00
# max 1.00 1.00 310.00
🎯 应用场景
- 快速了解数据范围: 通过min和max判断是否有异常值
- 评估数据集中趋势: 通过mean和median(50%)判断数据中心位置
- 评估数据离散程度: 通过std判断数据波动大小
- 检测数据偏态: 比较mean和median,判断数据是否偏态分布
2.3 数值型数据可视化
💡 知识点:三种常用图表
数值型数据可通过直方图、箱线图、密度曲线图来展示分布特征。
2.3.1 直方图(Histogram)
📌 核心概念
直方图将数据分成若干区间(bins),统计每个区间的频数,展示数据的分布形态。
📝 代码示例
python
# 创建画布
fig = plt.figure(figsize=(16, 4), dpi=100)
# 添加子图
fig.add_subplot(1, 3, 1)
# 绘制直方图
data['员工满意度'].plot(kind='hist')
# 添加标题
plt.title('员工满意度分布情况')
# 显示图像
plt.show()
🎯 应用场景
- 观察数据的分布形态(正态分布、偏态分布等)
- 识别数据的集中区间
- 发现异常值或离群点
2.3.2 箱线图(Box Plot)
📌 核心概念
箱线图通过五数概括(最小值、Q1、中位数、Q3、最大值)展示数据的分布和离群点。
📝 代码示例
python
# 绘制箱线图
data['考核评分'].plot(kind='box')
plt.title('考核评分分布情况')
plt.show()
📊 箱线图结构解读
最大值 ─────┐
│
Q3 ────┬────┤
│ │ ← 箱体(IQR:四分位距)
中位数 ├────┤
│ │
Q1 ────┴────┤
│
最小值 ─────┘
○ ← 离群点(超出1.5倍IQR的点)
🎯 应用场景
- 快速识别离群点
- 比较多组数据的分布差异
- 评估数据的对称性
2.3.3 密度曲线图(KDE)
📌 核心概念
核密度估计图(Kernel Density Estimation)是对直方图的平滑化,展示数据的概率密度分布。
📝 代码示例
python
# 方法1:使用seaborn
import seaborn as sns
sns.kdeplot(data['每月在公司工作时间'])
plt.title('每月在公司工作时间分布情况')
plt.show()
# 方法2:使用pandas(可能出现警告)
data['每月在公司工作时间'].plot(kind='kde')
plt.title('每月在公司工作时间分布情况')
plt.show()
⚠️ 注意事项
- Pandas的
plot(kind='kde')在某些版本可能产生警告 - 推荐使用
seaborn.kdeplot(),更稳定且功能更强
🔍 对比说明:直方图 vs 密度曲线图
| 特性 | 直方图 | 密度曲线图 |
|---|---|---|
| 展示方式 | 柱状图 | 平滑曲线 |
| Y轴含义 | 频数 | 概率密度 |
| 优点 | 直观、易理解 | 平滑、美观 |
| 缺点 | 受bins影响大 | 可能过度平滑 |
2.3.4 多子图布局
💡 知识点:创建多子图画布
使用figure()和add_subplot()创建包含多个图表的画布。
📝 代码示例
python
# 创建画布:宽16英寸,高4英寸,分辨率100dpi
fig1 = plt.figure(figsize=(16, 4), dpi=100)
# 添加第一个子图(1行3列的第1个位置)
fig1.add_subplot(1, 3, 1)
data['员工满意度'].plot(kind='hist')
plt.title('员工满意度分布情况')
# 添加第二个子图(1行3列的第2个位置)
fig1.add_subplot(1, 3, 2)
data['考核评分'].plot(kind='box')
plt.title('考核评分分布情况')
# 添加第三个子图(1行3列的第3个位置)
fig1.add_subplot(1, 3, 3)
sns.kdeplot(data['每月在公司工作时间'])
plt.title('每月在公司工作时间分布情况')
# 显示所有子图
plt.show()
📊 add_subplot()参数说明
| 参数格式 | 含义 | 示例 |
|---|---|---|
| (nrows, ncols, index) | 行数、列数、位置 | (2, 3, 1) |
| 简写形式 | 三位数字 | 231 等同于 (2,3,1) |
💎 最佳实践
python
✅ 推荐:使用元组形式,代码更清晰
fig.add_subplot(2, 3, 1)
✅ 推荐:设置合适的figsize和dpi
fig = plt.figure(figsize=(15, 10), dpi=100)
❌ 避免:dpi设置过高导致渲染慢
fig = plt.figure(dpi=300) # 通常100-150即可
2.4 类别型数据描述分析
📌 核心概念
类别型数据(离散型数据)通过频数统计和分类图表来描述其分布特征。
🔧 函数:select_dtypes() + describe()
💡 知识点:筛选特定类型的列
使用select_dtypes()可以筛选出指定数据类型的列进行分析。
📝 代码示例
python
# 筛选类别型数据(object类型)
categorical_data = data.select_dtypes('object')
# 查看类别型数据的描述统计
categorical_data.describe()
# 输出示例:
# 部门 薪水
# count 15000 15000
# unique 10 3
# top sales low
# freq 4140 7316
📊 类别型describe()输出解读
| 统计量 | 含义 | 说明 |
|---|---|---|
| count | 非空元素数目 | 该列有多少个非空值 |
| unique | 唯一值数量 | 去重后有多少个不同类别 |
| top | 众数 | 出现次数最多的类别 |
| freq | 众数频数 | 众数出现的次数 |
🔧 函数:value_counts()
💡 知识点:统计每个类别的频数
value_counts()返回每个唯一值的出现次数,默认降序排列。
📝 代码示例
python
# 统计单个列的类别分布
data['部门'].value_counts()
# 输出示例:
# sales 4140
# technical 2720
# support 2229
# IT 1227
# ...
# 循环查看所有类别型列的详细分布
for col in data.select_dtypes('object'):
print(f"\n{col}列的分布情况:")
print(data[col].value_counts())
📊 value_counts()参数说明
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| normalize | bool | 是否返回比例 | False |
| sort | bool | 是否排序 | True |
| ascending | bool | 升序/降序 | False |
| dropna | bool | 是否排除NaN | True |
💎 最佳实践
python
✅ 推荐:查看比例分布
data['薪水'].value_counts(normalize=True)
✅ 推荐:重置索引便于后续操作
data['region'].value_counts().reset_index()
2.5 类别型数据可视化
💡 知识点:三种常用图表
类别型数据可通过柱形图、条形图、饼图来展示分布情况。
2.5.1 柱形图(Bar Chart)
📝 代码示例
python
# 绘制垂直柱形图
data['项目数量'].value_counts().plot(kind='bar', rot=0)
plt.title('项目数量分布可视化')
plt.show()
📊 参数说明
| 参数 | 含义 | 常用值 |
|---|---|---|
| kind | 图表类型 | 'bar' |
| rot | 标签旋转角度 | 0, 45, 90 |
| color | 颜色 | 颜色名或十六进制 |
2.5.2 条形图(Horizontal Bar)
📝 代码示例
python
# 绘制水平条形图
data['司龄'].value_counts().plot(kind='barh', rot=0)
plt.title('司龄分布可视化')
plt.show()
🔍 对比说明:柱形图 vs 条形图
| 特性 | 柱形图(bar) | 条形图(barh) |
|---|---|---|
| 方向 | 垂直 | 水平 |
| 适用场景 | 类别少 | 类别多、标签长 |
| kind参数 | 'bar' | 'barh' |
2.5.3 饼图(Pie Chart)
📝 代码示例
python
# 绘制饼图
data['工作事故'].value_counts().plot(
kind='pie',
autopct='%.2f%%' # 显示百分比,保留2位小数
)
plt.title('工作事故分布可视化')
plt.show()
📊 饼图参数说明
| 参数 | 含义 | 示例 |
|---|---|---|
| autopct | 百分比格式 | '%.2f%%' |
| startangle | 起始角度 | 90 |
| explode | 突出显示 | [0.1, 0, 0] |
| shadow | 阴影效果 | True |
⚠️ 注意事项
- 饼图适合展示占比关系,类别不宜超过7个
autopct='%.2f%%'中的%%表示显示百分号符号- 饼图会自动计算百分比,无需手动计算
3. 分组分析
📌 核心概念
分组分析(GroupBy)是将数据按照一个或多个字段分组,然后对每组数据进行聚合计算,是数据分析中最重要的操作之一。
3.1 基础分组操作
🔧 函数:DataFrame.groupby()
💡 知识点:分组的基本语法
groupby()将数据按指定列分组,返回一个GroupBy对象,需要配合聚合函数使用。
📝 代码示例
python
# 按单个字段分组,计算均值
result = data.groupby(by='是否离职')['员工满意度'].mean()
# 输出示例:
# 是否离职
# 0 0.666810
# 1 0.440098
# Name: 员工满意度, dtype: float64
📊 groupby()核心参数
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| by | str/list | 分组依据的列名 | 必填 |
| as_index | bool | 分组键是否作为索引 | True |
| sort | bool | 是否对分组键排序 | True |
💡 知识点:as_index参数的作用
📝 代码示例
python
# as_index=True(默认):分组键作为行索引
result1 = data.groupby(by='是否离职')['员工满意度'].mean()
# 输出:
# 是否离职
# 0 0.666810
# 1 0.440098
# as_index=False:分组键作为普通列
result2 = data.groupby(by='是否离职', as_index=False)['员工满意度'].mean()
# 输出:
# 是否离职 员工满意度
# 0 0 0.666810
# 1 1 0.440098
🔍 对比说明
| as_index | 分组键位置 | 适用场景 |
|---|---|---|
| True | 行索引 | 快速查看结果 |
| False | 普通列 | 需要进一步处理数据 |
💎 最佳实践
python
✅ 推荐:需要继续操作时使用as_index=False
result = data.groupby(by='部门', as_index=False)['考核评分'].mean()
result.sort_values(by='考核评分', ascending=False)
❌ 避免:as_index=True时难以排序
result = data.groupby(by='部门')['考核评分'].mean()
result.sort_values(ascending=False) # 可以,但不够直观
3.2 多字段分组
💡 知识点:按多个字段分组
传入列名列表可实现多层级分组,适用于交叉分析场景。
📝 代码示例
python
# 按两个字段分组
result = data.groupby(
by=['部门', '是否离职'],
as_index=False
)['员工满意度'].max()
# 输出示例:
# 部门 是否离职 员工满意度
# 0 IT 0 1.00
# 1 IT 1 1.00
# 2 sales 0 1.00
# 3 sales 1 1.00
🎯 应用场景
- 交叉分析:同时考虑多个维度
- 细分市场分析:按地区+产品类别分组
- 对比分析:按时间+类别分组
3.3 常用聚合函数
💡 知识点:GroupBy对象支持的聚合方法
📊 聚合函数列表
| 函数 | 功能 | 示例 |
|---|---|---|
| mean() | 均值 | .mean() |
| sum() | 求和 | .sum() |
| count() | 计数 | .count() |
| max() | 最大值 | .max() |
| min() | 最小值 | .min() |
| std() | 标准差 | .std() |
| var() | 方差 | .var() |
| median() | 中位数 | .median() |
| describe() | 描述统计 | .describe() |
📝 代码示例
python
# 1. 按部门分组,计算考核评分均值
data.groupby(by='部门', as_index=False)['考核评分'].mean()
# 2. 按部门分组,计算工作时长的8个统计量
data.groupby(by='部门')['每月在公司工作时间'].describe()
# 3. 按多字段分组,计算最大值
data.groupby(by=['部门', '是否离职'], as_index=False)['员工满意度'].max()
3.4 多字段多聚合:agg()函数
🔧 函数:agg()
📌 核心概念
agg()(aggregate的缩写)是专门用于分组后聚合的函数,支持对不同字段应用不同的聚合函数。
💡 知识点:agg()的三种用法
用法1:单字段单聚合
📝 代码示例
python
# 对单个字段应用单个聚合函数
data.groupby(by='项目数量').agg({'员工满意度': 'mean'})
用法2:单字段多聚合
📝 代码示例
python
# 对单个字段应用多个聚合函数
data.groupby(by='部门', as_index=False).agg({
'员工满意度': ['max', 'min'],
'每月在公司工作时间': ['mean']
})
用法3:多字段多聚合(最常用)
📝 代码示例
python
# 对不同字段应用不同的聚合函数
data1 = data.groupby(by='项目数量').agg({
'员工满意度': ['mean'], # 计算均值
'考核评分': ['max'] # 计算最大值
})
# 输出示例:
# 员工满意度 考核评分
# mean max
# 项目数量
# 2 0.478760 1.00
# 3 0.571429 1.00
# 4 0.633929 1.00
⚠️ 注意事项:多层索引问题
当使用agg()返回多个聚合结果时,列名会变成多层索引(MultiIndex)。
📝 代码示例
python
# 查看列名结构
data1.columns
# 输出:MultiIndex([('员工满意度', 'mean'),
# ( '考核评分', 'max')])
# 方法1:使用元组访问列
data1.sort_values(by=[('员工满意度', 'mean')], ascending=False)
# 方法2:重命名列(扁平化)
data1.columns = ['员工满意度均值', '考核评分最大值']
data1.sort_values(by='员工满意度均值', ascending=False)
💎 最佳实践
python
✅ 推荐:使用字典明确指定聚合函数
data.groupby('部门').agg({
'员工满意度': ['mean', 'std'],
'考核评分': ['max', 'min']
})
✅ 推荐:多层索引时使用元组访问
result.sort_values(by=[('员工满意度', 'mean')], ascending=False)
❌ 避免:混用字符串和列表
data.groupby('部门').agg({'员工满意度': 'mean', '考核评分': ['max']})
3.5 综合练习
📝 练习1:单字段多聚合
python
# 按照部门分组,计算员工满意度的最大值和最小值,工作时长的均值
data.groupby(by='部门', as_index=False).agg({
'员工满意度': ['max', 'min'],
'每月在公司工作时间': ['mean']
})
📝 练习2:多字段聚合
python
# 按照司龄分组,计算工作时长均值和项目数量的标准差
data.groupby(by='司龄').agg({
'每月在公司工作时间': ['mean'],
'项目数量': ['std']
})
📝 练习3:多层分组多聚合
python
# 按照部门和薪水分组,计算员工满意度的均值和标准差
data.groupby(by=['部门', '薪水']).agg({
'员工满意度': ['mean', 'std']
})
4. 数据透视表
📌 核心概念
数据透视表(Pivot Table)是一种强大的数据汇总工具,本质是分组聚合的可视化展现,可以快速生成交叉分析表。
🔧 函数:pd.pivot_table()
4.1 基本语法
📊 参数说明
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| data | DataFrame | 数据源 | 必填 |
| index | str/list | 行分组键 | 必填 |
| columns | str/list | 列分组键 | None |
| values | str/list | 要聚合的数据列 | 必填 |
| aggfunc | str/dict/list | 聚合函数 | 'mean' |
| margins | bool | 是否添加汇总行/列 | False |
| fill_value | scalar | 填充缺失值 | None |
💡 知识点:透视表的结构
列分组键(columns)
项目数量2 项目数量3 项目数量4
行分组键(index)
部门IT 0.618 0.650 0.720
部门sales 0.479 0.571 0.634
4.2 基础透视表
📝 代码示例
python
# 按照部门和项目数量分组,得到员工满意度均值
result = pd.pivot_table(
index='部门', # 行分组键
columns='项目数量', # 列分组键
values=['员工满意度'], # 要统计的数据
aggfunc=['mean'], # 聚合函数(默认就是mean)
data=data, # 数据源
margins=True # 添加汇总行列
)
# 输出示例:
# 员工满意度
# mean
# 项目数量 2 3 4 All
# 部门
# IT 0.618 0.650 0.720 0.650
# sales 0.479 0.571 0.634 0.550
# All 0.500 0.600 0.680 0.600
⚠️ 注意事项
margins=True会在最后添加"All"行和列,显示总体统计- 列分组键的值会成为列名
- 如果某个组合没有数据,会显示NaN
4.3 多值多聚合透视表
📝 代码示例
python
# 按照是否离职和司龄分组,计算工作时间均值和考核评分标准差
df2 = pd.pivot_table(
data=data,
index='司龄', # 行:司龄
columns='是否离职', # 列:是否离职
values=['每月在公司工作时间', '考核评分'], # 多个统计字段
aggfunc={
'每月在公司工作时间': ['mean'], # 工作时间计算均值
'考核评分': 'std' # 考核评分计算标准差
}
)
# 保存结果到CSV
df2.to_csv('df2.csv')
🔍 对比说明:groupby vs pivot_table
| 特性 | groupby | pivot_table |
|---|---|---|
| 结果形式 | 长格式 | 宽格式(交叉表) |
| 可读性 | 一般 | 更直观 |
| 灵活性 | 更灵活 | 固定格式 |
| 适用场景 | 复杂聚合 | 交叉分析 |
💎 最佳实践
python
✅ 推荐:需要交叉分析时使用pivot_table
pd.pivot_table(index='部门', columns='薪水', values='员工满意度', aggfunc='mean', data=data)
✅ 推荐:需要多种聚合时使用groupby
data.groupby('部门').agg({'员工满意度': ['mean', 'std', 'max', 'min']})
4.4 计算离职率实战
💡 知识点:使用透视表计算比率
📝 代码示例
python
# 计算不同项目数量的离职率
df3 = pd.pivot_table(
index='项目数量',
columns='是否离职',
values='部门', # 使用任意列进行计数
aggfunc='count', # 计数聚合
data=data
)
# 计算离职率 = 离职人数 / 总人数
df3['离职率'] = df3[1] / (df3[0] + df3[1])
# 按离职率降序排列
df3.sort_values(by='离职率', ascending=False)
# 输出示例:
# 是否离职 0 1 离职率
# 项目数量
# 7 256 916 0.781
# 6 215 127 0.371
# 2 2388 3875 0.619
🎯 应用场景
- 计算转化率、流失率等业务指标
- 对比不同分组的比率差异
- 识别高风险群体
5. 交叉表
📌 核心概念
交叉表(Cross Tabulation)是数据透视表的特殊形式,专门用于统计分类变量的频数分布,默认聚合函数是计数。
🔧 函数:pd.crosstab()
5.1 基本用法
📝 代码示例
python
# 计算不同部门的离职率
df4 = pd.crosstab(
index=data['部门'], # 行分组
columns=data['是否离职'] # 列分组
)
# 输出示例:
# 是否离职 0 1
# 部门
# IT 767 460
# sales 2720 1420
# support 1473 756
# 计算离职率
df4['离职率'] = df4[1] / (df4[0] + df4[1])
📊 crosstab()参数说明
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| index | Series/array | 行分组数据 | 必填 |
| columns | Series/array | 列分组数据 | 必填 |
| values | Series/array | 聚合的值 | None |
| aggfunc | function | 聚合函数 | count |
| margins | bool | 添加汇总 | False |
| normalize | bool/str | 归一化 | False |
5.2 交叉表 vs 透视表
🔍 对比说明
| 特性 | crosstab | pivot_table |
|---|---|---|
| 默认聚合 | 计数(count) | 均值(mean) |
| 参数数量 | 较少 | 较多 |
| 灵活性 | 专注计数 | 支持各种聚合 |
| 使用场景 | 频数统计 | 通用聚合分析 |
💡 知识点:何时使用哪个?
python
✅ 使用crosstab:纯粹的分类计数
pd.crosstab(index=df['region'], columns=df['category'])
✅ 使用pivot_table:需要其他聚合函数
pd.pivot_table(index='region', columns='category', values='sales', aggfunc='sum', data=df)
⚠️ 重要说明
- 交叉表能完成的,透视表都能完成(设置
aggfunc='count') - 但交叉表语法更简洁,专门用于计数场景
- 透视表功能更强大,支持复杂的聚合需求
📝 等价代码示例
python
# 方法1:使用crosstab
result1 = pd.crosstab(index=df['region'], columns=df['category'])
# 方法2:使用pivot_table(等价)
result2 = pd.pivot_table(
index='region',
columns='category',
values='order_id', # 任意列
aggfunc='count',
data=df
)
5.3 unstack()方法
💡 知识点:将多层索引转换为透视表格式
📝 代码示例
python
# 使用groupby + unstack实现交叉表效果
result = data.groupby(by=['region', 'category'])['order_id'].count().unstack()
# 等价于
result = pd.crosstab(index=df['region'], columns=df['category'])
🔍 对比说明:三种方法
| 方法 | 代码复杂度 | 灵活性 | 推荐度 |
|---|---|---|---|
| crosstab | ⭐ 简单 | ⭐⭐ 中等 | ⭐⭐⭐ |
| pivot_table | ⭐⭐ 中等 | ⭐⭐⭐ 高 | ⭐⭐⭐ |
| groupby+unstack | ⭐⭐⭐ 复杂 | ⭐⭐⭐ 高 | ⭐⭐ |
6. 数据可视化
6.1 DataFrame绘图方法
🔧 函数:DataFrame.plot()
📌 核心概念
Pandas的DataFrame和Series对象内置了plot()方法,可以快速创建各种图表。
📊 plot()参数说明
| 参数 | 类型 | 说明 | 常用值 |
|---|---|---|---|
| kind | str | 图表类型 | 'line', 'bar', 'barh', 'hist', 'box', 'kde', 'scatter', 'pie' |
| x | str | X轴数据列 | 列名 |
| y | str | Y轴数据列 | 列名 |
| figsize | tuple | 图表尺寸 | (8, 6) |
| title | str | 图表标题 | 字符串 |
| rot | int | 标签旋转角度 | 0, 45, 90 |
| color | str/list | 颜色 | 颜色名或列表 |
6.2 常用图表类型
6.2.1 柱状图
📝 代码示例
python
# 分组后绘制柱状图
df.groupby(by='category')['sales'].sum().plot(kind='bar', rot=0)
plt.title('各产品类别的销售总额柱状图')
plt.show()
6.2.2 折线图
📝 代码示例
python
# 绘制时间序列折线图
df.plot(x='date', y='sales', kind='line')
plt.title('销售额随时间变化的折线图')
plt.ylabel('销售额')
plt.show()
6.2.3 散点图
📝 代码示例
python
# 绘制两个变量的散点图
df.plot(x='quantity', y='sales', kind='scatter')
plt.title('销售额与数量的散点图')
plt.show()
6.3 自定义绘图
💡 知识点:使用Matplotlib进行精细控制
📝 代码示例
python
# 创建画布
plt.figure(figsize=(8, 6))
# 准备数据
x = df.groupby('category')['sales'].sum().index
y = df.groupby('category')['sales'].sum().values
# 绘制柱状图
plt.bar(x, y, color=['#1f77b4', '#ff7f0e', '#2ca02c'])
# 设置标题和标签
plt.title('各商品类别销售总额', fontsize=14, pad=20)
plt.xlabel('商品类别', fontsize=12)
plt.ylabel('总销售额(元)', fontsize=12)
# 添加网格线
plt.grid(axis='y', alpha=0.3)
# 自动调整布局
plt.tight_layout()
# 显示图表
plt.show()
📊 常用参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
| figsize | 图表尺寸(宽,高) | (8, 6) |
| fontsize | 字体大小 | 14 |
| pad | 标题与图表间距 | 20 |
| alpha | 透明度 | 0.3 |
| color | 颜色列表 | ['#1f77b4', '#ff7f0e'] |
💎 最佳实践
python
✅ 推荐:使用tight_layout()自动调整布局
plt.tight_layout()
✅ 推荐:设置合适的figsize和fontsize
plt.figure(figsize=(10, 6))
plt.title('标题', fontsize=14)
✅ 推荐:添加网格线提高可读性
plt.grid(axis='y', alpha=0.3)
7. 综合练习
7.1 数据排序
🔧 函数:DataFrame.sort_values()
📝 代码示例
python
# 找出销售额最高的5笔订单
df.sort_values(by='sales', ascending=False).head()
# 输出示例:
# order_id product category region sales quantity
# 15 1016 电视 电子产品 华东 4998 9
# 3 1004 手机 电子产品 华南 4800 7
📊 参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
| by | 排序依据的列 | 必填 |
| ascending | 升序/降序 | True |
| inplace | 是否原地修改 | False |
| na_position | NaN值位置 | 'last' |
7.2 索引重置
🔧 函数:reset_index()
💡 知识点:将索引转换为普通列
📝 代码示例
python
# value_counts()结果的索引是类别值
counts = df['region'].value_counts()
# 输出:
# 华东 8
# 华南 7
# 华北 5
# 重置索引,将类别值变为普通列
counts_df = df['region'].value_counts().reset_index()
# 输出:
# region count
# 0 华东 8
# 1 华南 7
# 2 华北 5
🎯 应用场景
- 将聚合结果转换为DataFrame便于后续操作
- 将多层索引展平
- 为结果添加序号列
7.3 新增计算列
💡 知识点:基于现有列创建新列
📝 代码示例
python
# 新建单价列:销售额除以数量
df['unit_price'] = df['sales'] / df['quantity']
# 四舍五入保留2位小数
df['unit_price'] = np.round(df['unit_price'], 2)
# 查看结果
df[['sales', 'quantity', 'unit_price']].head()
🔧 函数:np.round()
📊 参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
| a | 要四舍五入的数组 | df['unit_price'] |
| decimals | 保留小数位数 | 2 |
💎 最佳实践
python
✅ 推荐:使用向量化操作
df['unit_price'] = df['sales'] / df['quantity']
❌ 避免:使用循环(效率低)
for i in range(len(df)):
df.loc[i, 'unit_price'] = df.loc[i, 'sales'] / df.loc[i, 'quantity']
7.4 综合练习题解答
📝 练习1:找出销售额最高的5笔订单
python
df.sort_values(by='sales', ascending=False).head()
📝 练习2:统计每个区域的订单数量
python
df['region'].value_counts().reset_index()
📝 练习3:得到各商品类别的总销售额
python
df.groupby(by='category', as_index=False)['sales'].sum()
📝 练习4:得到各区域的总销售额
python
df.groupby(by='region', as_index=False)['sales'].sum()
📝 练习5:使用pivot_table统计各地区-各商品类别的平均销售额
python
pd.pivot_table(
data=df,
index='region',
columns='category',
values='sales',
aggfunc=['mean']
)
📝 练习6:绘制各产品类别的销售总额柱状图
python
df.groupby(by='category')['sales'].sum().plot(kind='bar', rot=0)
plt.title('各产品类别的销售总额柱状图')
plt.show()
📝 练习7:绘制销售额随时间变化的折线图
python
df.plot(x='date', y='sales', kind='line')
plt.title('销售额随时间变化的折线图')
plt.ylabel('销售额')
plt.show()
📝 练习8:绘制销售额与数量的散点图
python
df.plot(x='quantity', y='sales', kind='scatter')
plt.title('销售额与数量的散点图')
plt.show()
📝 练习9:新建单价列
python
df['unit_price'] = df['sales'] / df['quantity']
df['unit_price'] = np.round(df['unit_price'], 2)
📝 练习10:各区域不同商品类别订单数量
python
# 方法1:使用crosstab
pd.crosstab(index=df['region'], columns=df['category'])
# 方法2:使用groupby + unstack
df.groupby(by=['region', 'category'])['order_id'].count().unstack()
8. 知识点速查表
📊 核心函数速查
⭐ 基础必学
| 函数 | 功能 | 语法示例 |
|---|---|---|
info() |
数据概览 | data.info() |
describe() |
描述统计 | data.describe() |
value_counts() |
频数统计 | data['列名'].value_counts() |
groupby() |
分组 | data.groupby('列名') |
plot() |
绘图 | data.plot(kind='bar') |
⭐⭐ 进阶提升
| 函数 | 功能 | 语法示例 |
|---|---|---|
agg() |
多聚合 | data.groupby('列').agg({'列1': 'mean', '列2': 'sum'}) |
pivot_table() |
数据透视表 | pd.pivot_table(index='行', columns='列', values='值', data=data) |
crosstab() |
交叉表 | pd.crosstab(index=data['列1'], columns=data['列2']) |
select_dtypes() |
筛选类型 | data.select_dtypes('object') |
reset_index() |
重置索引 | result.reset_index() |
⭐⭐⭐ 高级技巧
| 函数 | 功能 | 语法示例 |
|---|---|---|
unstack() |
索引转列 | data.groupby(['列1', '列2']).count().unstack() |
sort_values() |
排序 | data.sort_values(by='列', ascending=False) |
add_subplot() |
添加子图 | fig.add_subplot(2, 3, 1) |
sns.kdeplot() |
密度曲线 | sns.kdeplot(data['列']) |
📈 图表类型速查
| 图表类型 | kind参数 | 适用数据 | 主要用途 |
|---|---|---|---|
| 直方图 | 'hist' | 数值型 | 查看分布形态 |
| 箱线图 | 'box' | 数值型 | 识别离群点 |
| 密度图 | 'kde' | 数值型 | 平滑分布曲线 |
| 柱形图 | 'bar' | 类别型 | 比较类别频数 |
| 条形图 | 'barh' | 类别型 | 类别多时使用 |
| 饼图 | 'pie' | 类别型 | 展示占比关系 |
| 折线图 | 'line' | 时间序列 | 展示趋势变化 |
| 散点图 | 'scatter' | 两个数值 | 查看相关性 |
🎯 分析流程速查
数据导入
↓
data.info() ──→ 检查数据完整性
↓
数据类型判断
↓
┌───────────────┬───────────────┐
│ 数值型数据 │ 类别型数据 │
│ │ │
│ describe() │ value_counts()│
│ hist/box/kde │ bar/barh/pie │
└───────────────┴───────────────┘
↓
分组分析
↓
┌───────────────┬───────────────┐
│ groupby() │ pivot_table() │
│ + agg() │ / crosstab() │
└───────────────┴───────────────┘
↓
结果可视化
💡 常见问题速查
Q1: 中文显示乱码?
python
✅ 解决方案:
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
Q2: 如何选择分组函数?
python
✅ 简单计数 → crosstab()
✅ 交叉分析 → pivot_table()
✅ 复杂聚合 → groupby() + agg()
Q3: 多层索引如何访问?
python
✅ 使用元组:
result.sort_values(by=[('列名', '聚合函数')], ascending=False)
✅ 或重命名:
result.columns = ['新列名1', '新列名2']
Q4: 如何计算比率?
python
✅ 先用pivot_table或crosstab统计频数
df = pd.crosstab(index=data['列1'], columns=data['列2'])
✅ 再计算比率
df['比率'] = df[1] / (df[0] + df[1])
🔗 关联知识点
描述性统计分析
├─ 数据完整性 → info()
├─ 数值型分析 → describe(), hist, box, kde
└─ 类别型分析 → value_counts(), bar, pie
分组分析
├─ 单层分组 → groupby(by='列')
├─ 多层分组 → groupby(by=['列1', '列2'])
└─ 多聚合 → agg({'列1': 'mean', '列2': ['max', 'min']})
数据透视
├─ 通用透视 → pivot_table()
├─ 频数统计 → crosstab()
└─ 索引转换 → unstack()
数据可视化
├─ 快速绘图 → DataFrame.plot()
├─ 精细控制 → matplotlib
└─ 统计图表 → seaborn
💎 最佳实践总结
1. 数据分析流程
python
# 第一步:导入数据
data = pd.read_csv('data.csv', encoding='gbk')
# 第二步:数据概览
data.info()
data.head()
# 第三步:描述统计
data.describe() # 数值型
data.select_dtypes('object').describe() # 类别型
# 第四步:分组分析
data.groupby('分组列').agg({'统计列': '聚合函数'})
# 第五步:可视化
data.plot(kind='图表类型')
2. 代码规范
python
✅ 推荐:使用as_index=False便于后续操作
data.groupby(by='列', as_index=False)['值'].mean()
✅ 推荐:为图表添加标题和标签
plt.title('标题')
plt.xlabel('X轴')
plt.ylabel('Y轴')
✅ 推荐:使用字典明确指定聚合函数
data.groupby('列').agg({'列1': 'mean', '列2': ['max', 'min']})
3. 性能优化
python
🚀 使用向量化操作代替循环
df['新列'] = df['列1'] / df['列2']
🚀 使用内置函数代替自定义函数
data.groupby('列')['值'].mean()
4. 常见错误避免
python
❌ 忘记设置中文字体
plt.rcParams['font.sans-serif'] = 'SimHei'
❌ 多层索引访问错误
result.sort_values(by='列名') # 错误
result.sort_values(by=[('列名', '聚合函数')]) # 正确
❌ 混淆crosstab和pivot_table的参数
pd.crosstab(index='列1', columns='列2') # 错误
pd.crosstab(index=data['列1'], columns=data['列2']) # 正确
🎓 学习建议
1. 理解核心概念
- 描述性统计的目的是快速了解数据
- 分组分析的本质是分而治之
- 透视表是分组聚合的可视化展现
2. 多练习实战
- 使用真实数据集练习(如HR数据、销售数据)
- 尝试不同的分组组合和聚合函数
- 对比不同可视化方法的效果
3. 掌握工具选择
- 简单计数 →
value_counts()或crosstab() - 交叉分析 →
pivot_table() - 复杂聚合 →
groupby()+agg() - 快速可视化 →
DataFrame.plot() - 精美图表 →
matplotlib+seaborn
4. 注意细节
- 始终检查数据类型(数值型 vs 类别型)
- 注意缺失值的处理
- 合理选择聚合函数(均值、中位数、求和等)
- 为图表添加清晰的标题和标签
💡 核心要点 :Pandas的描述分析和分组分析是数据分析的基础,掌握这些技能可以快速从数据中提取有价值的信息。记住:先了解数据(describe),再分组分析(groupby),最后可视化展示(plot)。