在 Pandas 中,将 列式数据(长格式) 转换为 二维交叉形式(宽格式) 的操作通常称为 重塑 或 数据透视。
经过统计得到多维度指标数据
常见场景:指定多个维度,计算聚合后的指标。
示例的目标:统计电影评分数据集,看每个月份每个分数被评分多少次:月份、分数(1-5)、次数。
引入包:
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
读入数据:
file_path = './data/ratings.dat'
df_ratings = pd.read_csv(
file_path,
header=None,
sep='::',
engine='python',
names='UserID::MovieID::Rating::Timestamp'.split('::')
)
查看数据:
根据Timestamp,新增一列:
df_ratings['DateTime'] = pd.to_datetime(df_ratings['Timestamp'], unit='s')
结果变为:
查看下数据类型:
分组统计:
df_ratings_groups = df_ratings.groupby([df_ratings['DateTime'].dt.month, 'Rating'])['UserID'].agg(pv='count')
结果的前面部分截图:
使用unstack实现数据二维透视
要实现的目标:画图对比不同月份的不同评分的数量趋势。
df_ratings_unstack = df_ratings_groups.unstack()
查看二维透视的数据:
画图:
df_ratings_unstack.plot()
plt.show()
unstack 和 stack 是互逆操作:
# unstack 和 stack 是互逆操作
df_ratings_unstack.stack(future_stack=True).head(10)
执行的结果,又回到了以前的格式:
使用pivot简化透视
pivot方法相当于对DataFrame使用set_index创建分层索引,然后调用unstack。
先看看统计结果的样式:
重置索引:
df_ratings_reset = df_ratings_groups.reset_index()
查看结果:
用pivot变形:
df_ratings_pivot = df_ratings_reset.pivot(columns='Rating', index='DateTime', values='pv')
查看结果:
画图:
df_ratings_pivot.plot()
plt.show()
画出的图形:
stack、unstack、pivot的语法
stack
DataFrame.stack(level=-1, dropna=<no_default>, sort=<no_default>, future_stack=False)
- stack将列变成行索引
level 参数的含义
level 参数用于指定要堆叠的列层级的索引或名称。它可以接受以下类型的值:
- 整数(int):表示要堆叠的列层级的索引(从 0 开始)。例如,level=0 表示堆叠第 1 个列层级,level=1 表示堆叠第 2 个列层级。
- 字符串(str):如果列是多层索引(MultiIndex),可以通过列层级的名称指定要堆叠的层级。
- 列表(list):可以传递一个列表来指定多个层级进行堆叠。
- 默认值 level=-1:默认情况下,level=-1 表示堆叠最内层的列层级。
- 对于单层列索引,默认会堆叠所有列。
- 对于多层列索引,可以通过 level 指定堆叠的层级(索引或名称)。
示例:单层列索引
my_df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
查看结果:
直接调用 stack(),由于列是单层索引,所有列都会被堆叠:
my_stacked = my_df.stack()
查看结果:
unstack
DataFrame.unstack(level=-1, fill_value=None, sort=True)
DataFrame.unstack() 是 stack() 的逆操作,用于将行索引的某一层级“展开”为列。
level 参数的含义
level 参数用于指定要展开的行层级。它可以接受以下类型的值:
- 整数(int):表示要展开的行层级的索引(从 0 开始)。例如,level=0 表示展开第 1 个行层级,level=1 表示展开第 2个行层级。
- 字符串(str):如果行索引是多层索引(MultiIndex),可以通过行层级的名称指定要展开的层级。
- 默认值 level=-1:默认情况下,level=-1 表示展开最内层的行层级。
- 对于单层行索引,无法使用 unstack()。
- 对于多层行索引,可以通过 level 指定展开的层级(索引或名称)。
pivot
DataFrame.pivot(*, columns, index=<no_default>, values=<no_default>)
DataFrame.pivot() 是 Pandas 中用于数据重塑(reshape)的重要方法,它可以将长格式的数据转换为宽格式。pivot() 方法通过指定 index、columns 和 values 参数,将数据从“行”转换为“列”,从而实现数据的透视操作。
参数说明
- columns(必需):指定哪一列的值将作为新 DataFrame 的列名。该列中的唯一值将成为新 DataFrame 的列。
- index(可选,默认是当前索引):指定哪一列的值将作为新 DataFrame 的行索引。如果未指定,默认使用当前索引。
- values(可选):指定哪一列的值将填充新 DataFrame 的数据部分。如果未指定,默认使用所有剩余的列。
注意:
- index 和 columns 的组合必须是唯一的,否则会抛出错误。
- 如果某些组合不存在,结果中会填充 NaN。
示例:基本用法
DataFrame:
my_data2 = {
'Date': ['2025-01-01', '2025-01-01', '2025-01-02', '2025-01-02'],
'Variable': ['A', 'B', 'A', 'B'],
'Value': [100, 200, 300, 400]
}
my_df2 = pd.DataFrame(my_data2)
查看数据:
使用 pivot() 将 Variable 列的值转换为列名,Date 列作为行索引,Value 列作为数据:
my_df2.pivot(columns='Variable', index='Date', values='Value')
输出:
示例:未指定 values
如果未指定 values 参数,pivot() 会将所有剩余的列作为数据部分:
my_df2.pivot(columns='Variable', index='Date')
输出:
示例:未指定 index
如果未指定 index 参数,默认使用当前索引:
my_df2.pivot(columns='Variable', values='Value')
输出: