好的,各位观众老爷们,欢迎来到老码农的“数据变形计”专场!今天咱们要聊的,是数据分析界的一项神奇“易容术”——长数据变宽数据!
想象一下,你是一位精明能干的服装店老板,每天都要记录顾客的消费信息。传统的记录方式可能是这样的:
顾客ID | 日期 | 商品 | 价格 |
---|---|---|---|
1 | 2023-10-26 | 衬衫 | 100 |
1 | 2023-10-26 | 裤子 | 200 |
2 | 2023-10-26 | 鞋子 | 300 |
2 | 2023-10-27 | 帽子 | 50 |
1 | 2023-10-27 | 外套 | 400 |
这种数据结构,我们称之为“长数据”(Long Data)。它就像一条长长的记录,每一行都代表着一个观测值。
但是,如果你想更直观地看到每个顾客都买了什么,或者想按商品来分析销售情况,这种长数据就显得有些力不从心了。这时候,你就需要“易容术”——把长数据变成宽数据!
宽数据(Wide Data)是什么样的呢?它会把一些列的值变成新的列名,让数据更宽广、更扁平。比如,我们可以把上面的数据变成这样:
顾客ID | 2023-10-26_衬衫 | 2023-10-26_裤子 | 2023-10-26_鞋子 | 2023-10-27_帽子 | 2023-10-27_外套 |
---|---|---|---|---|---|
1 | 100 | 200 | NaN | NaN | 400 |
2 | NaN | NaN | 300 | 50 | NaN |
你看,是不是一目了然了?每个顾客购买的商品,都直接显示在了对应的列中。
那么,如何才能施展这种神奇的“易容术”呢?在Python的Pandas库中,有两个强大的法宝:pivot
和 pivot_table
。
接下来,就让老码农来为你详细解读这两个法宝的用法!
法宝一:pivot
– 简单粗暴,一锤定音!
pivot
方法就像一位简单粗暴的工匠,它只能处理最简单的情况。如果你的数据满足以下条件,那么 pivot
就是你的最佳选择:
- 没有重复的索引-列组合: 也就是说,对于相同的索引和列,只能有一个值。
- 不需要聚合函数: 你只需要把数据从长变宽,不需要进行任何计算。
pivot
方法的基本语法如下:
df.pivot(index='index_col', columns='columns_col', values='values_col')
index
:指定用作新表格索引的列名。columns
:指定用作新表格列名的列名。values
:指定填充新表格值的列名。
咱们还是用服装店的数据来举例,首先,我们创建一个DataFrame:
import pandas as pd
data = {'顾客ID': [1, 1, 2, 2, 1],
'日期': ['2023-10-26', '2023-10-26', '2023-10-26', '2023-10-27', '2023-10-27'],
'商品': ['衬衫', '裤子', '鞋子', '帽子', '外套'],
'价格': [100, 200, 300, 50, 400]}
df = pd.DataFrame(data)
print(df)
输出结果:
顾客ID 日期 商品 价格
0 1 2023-10-26 衬衫 100
1 1 2023-10-26 裤子 200
2 2 2023-10-26 鞋子 300
3 2 2023-10-27 帽子 50
4 1 2023-10-27 外套 400
现在,我们使用 pivot
方法,将“顾客ID”作为索引,“商品”作为列,“价格”作为值:
pivot_df = df.pivot(index='顾客ID', columns='商品', values='价格')
print(pivot_df)
输出结果:
商品 外套 帽子 衬衫 裤子 鞋子
顾客ID
1 400.0 NaN 100.0 200.0 NaN
2 NaN 50.0 NaN NaN 300.0
怎么样,是不是很简单? pivot
方法就像一把锋利的刻刀,直接把数据按照你的意愿雕刻成了想要的形状。
但是! pivot
方法有一个致命的缺点:它不能处理重复的索引-列组合。如果你的数据中存在这种情况,pivot
方法就会毫不留情地抛出一个错误,让你措手不及。 😱
举个例子,如果我们的数据中,顾客1在2023-10-26这一天买了两次衬衫,那么 pivot
方法就会报错:
data = {'顾客ID': [1, 1, 2, 2, 1, 1],
'日期': ['2023-10-26', '2023-10-26', '2023-10-26', '2023-10-27', '2023-10-27', '2023-10-26'],
'商品': ['衬衫', '裤子', '鞋子', '帽子', '外套', '衬衫'],
'价格': [100, 200, 300, 50, 400, 120]}
df = pd.DataFrame(data)
try:
pivot_df = df.pivot(index='顾客ID', columns='商品', values='价格')
print(pivot_df)
except ValueError as e:
print(f"Error: {e}")
输出结果:
Error: Index contains duplicate entries, cannot reshape
看到没? pivot
方法直接罢工了!
这时候,我们就需要请出我们的第二个法宝:pivot_table
!
法宝二:pivot_table
– 包容万象,化腐朽为神奇!
pivot_table
方法就像一位经验丰富的炼金术士,它不仅可以处理重复的索引-列组合,还可以进行各种聚合计算,把复杂的数据变成你想要的模样。
pivot_table
方法的基本语法如下:
pd.pivot_table(data, values='values_col', index='index_col', columns='columns_col', aggfunc='aggregate_function')
data
:指定要进行透视的数据。values
:指定填充新表格值的列名。index
:指定用作新表格索引的列名。columns
:指定用作新表格列名的列名。aggfunc
:指定聚合函数。常用的聚合函数包括:'mean'
(平均值)、'sum'
(求和)、'count'
(计数)、'min'
(最小值)、'max'
(最大值)等等。
咱们还是用刚才报错的数据来举例,这次我们使用 pivot_table
方法,并指定聚合函数为 'sum'
,表示对重复的索引-列组合的值进行求和:
pivot_table_df = pd.pivot_table(df, values='价格', index='顾客ID', columns='商品', aggfunc='sum')
print(pivot_table_df)
输出结果:
商品 外套 帽子 衬衫 裤子 鞋子
顾客ID
1 400.0 NaN 220.0 200.0 NaN
2 NaN 50.0 NaN NaN 300.0
你看,即使有重复的索引-列组合,pivot_table
方法也能轻松应对,并按照我们指定的聚合函数进行计算。
pivot_table
方法的强大之处还在于,它可以进行各种复杂的聚合计算。比如,我们可以计算每个顾客购买的商品数量:
pivot_table_df = pd.pivot_table(df, values='价格', index='顾客ID', columns='商品', aggfunc='count')
print(pivot_table_df)
输出结果:
商品 外套 帽子 衬衫 裤子 鞋子
顾客ID
1 1.0 NaN 2.0 1.0 NaN
2 NaN 1.0 NaN NaN 1.0
或者,我们可以计算每个顾客购买的商品价格的平均值:
pivot_table_df = pd.pivot_table(df, values='价格', index='顾客ID', columns='商品', aggfunc='mean')
print(pivot_table_df)
输出结果:
商品 外套 帽子 衬衫 裤子 鞋子
顾客ID
1 400.0 NaN 110.0 200.0 NaN
2 NaN 50.0 NaN NaN 300.0
总而言之,pivot_table
方法就像一位百变星君,可以根据你的需求,进行各种灵活的变形和计算。
pivot
vs. pivot_table
:一场巅峰对决!
说了这么多,相信大家对 pivot
和 pivot_table
都有了一定的了解。那么,它们之间到底有什么区别呢?我们来总结一下:
特性 | pivot |
pivot_table |
---|---|---|
处理重复值 | 无法处理,会报错 ❌ | 可以处理,需要指定聚合函数 ✅ |
聚合计算 | 不支持 ❌ | 支持,可以进行各种聚合计算 ✅ |
灵活性 | 较低 😔 | 较高 😊 |
使用场景 | 数据干净,没有重复值,不需要聚合计算时 🤓 | 数据复杂,可能存在重复值,需要进行聚合计算时 😎 |
简单来说,pivot
适合处理简单的数据变形,而 pivot_table
适合处理复杂的数据分析。就像一把瑞士军刀,pivot_table
功能更多,更实用。
实战演练:用 pivot_table
玩转电影评分数据!
光说不练假把式!为了让大家更好地掌握 pivot_table
的用法,我们来做一个实战演练。
假设我们有一份电影评分数据,包含了用户ID、电影ID和评分:
用户ID | 电影ID | 评分 |
---|---|---|
1 | 101 | 4 |
1 | 102 | 5 |
2 | 101 | 3 |
2 | 103 | 2 |
3 | 102 | 4 |
3 | 103 | 5 |
我们想要把这份数据变成宽数据,让每一行代表一个用户,每一列代表一部电影,单元格中的值代表用户对该电影的评分。
首先,我们创建一个DataFrame:
import pandas as pd
data = {'用户ID': [1, 1, 2, 2, 3, 3],
'电影ID': [101, 102, 101, 103, 102, 103],
'评分': [4, 5, 3, 2, 4, 5]}
df = pd.DataFrame(data)
print(df)
输出结果:
用户ID 电影ID 评分
0 1 101 4
1 1 102 5
2 2 101 3
3 2 103 2
4 3 102 4
5 3 103 5
现在,我们使用 pivot_table
方法,将“用户ID”作为索引,“电影ID”作为列,“评分”作为值:
pivot_table_df = pd.pivot_table(df, values='评分', index='用户ID', columns='电影ID')
print(pivot_table_df)
输出结果:
电影ID 101 102 103
用户ID
1 4.0 5.0 NaN
2 3.0 NaN 2.0
3 NaN 4.0 5.0
搞定!我们成功地把电影评分数据变成了宽数据,可以更方便地进行用户画像和电影推荐等分析。
高级技巧:玩转 pivot_table
的更多姿势!
除了基本的用法之外,pivot_table
还有很多高级技巧,可以让你玩转各种复杂的数据分析场景。
- 多层索引和列:
pivot_table
支持多层索引和列,可以让你更细粒度地分析数据。 - 自定义聚合函数: 除了内置的聚合函数之外,你还可以自定义聚合函数,满足更个性化的需求。
- 处理缺失值:
pivot_table
提供了fill_value
参数,可以让你自定义缺失值的填充方式。 - 添加总计:
pivot_table
提供了margins
参数,可以让你添加行和列的总计。
这些高级技巧,就留给大家自己去探索和学习啦!相信只要你多多实践,一定能成为 pivot_table
的高手!
总结:数据变形,其乐无穷!
今天,我们一起学习了如何使用 pivot
和 pivot_table
这两个法宝,将长数据变成宽数据。数据变形是数据分析中非常重要的一环,它可以帮助我们更好地理解数据、发现规律、做出决策。
希望通过今天的学习,大家能够掌握数据变形的技巧,在数据分析的道路上越走越远!
最后,老码农祝大家编码愉快,bug退散!咱们下期再见! 👋