深入了解 Pandas 中的层次化索引(Hierarchical Indexing)_续

数据重塑stack 与unstack函数

stack()

  • level:参数用于指定在多级列索引的情况下,要堆叠的列索引级别(level)。默认情况下,level 参数为 -1,表示堆叠最内层的列索引。
  • dropna: 参数是一个布尔值,用于指定是否在堆叠过程中删除包含缺失值(NaN)的行。默认情况下,dropna 为 True,表示删除包含缺失值的行。
  • name:参数用于指定生成的 Series 或 DataFrame 的列名称。可以指定一个字符串作为列名称,用于标识生成的 Series 或 DataFrame。
import numpy as np
import pandas as pd
from pandas import DataFrame, Series

columns = pd.MultiIndex.from_product([['期中', '期末'], ['语文', '数学']])
index = [['一班', '一班', '一班', '二班', '二班','二班'], 
         ['张三', '李四', '王五', '赵六', '田七', '孙八']]
data = np.random.randint(0, 150, size=(6, 4))
df = DataFrame(index=index, columns=columns, data=data)
df
期中期末
语文数学语文数学
一班张三36756101
李四11111611016
王五2138109141
二班赵六34215549
田七1167326148
孙八524894127
# 默认level = -1 将最内层的列索引旋转为最内层的行索引
df.stack()
期中期末
一班张三数学67101
语文356
李四数学11616
语文111110
王五数学38141
语文21109
二班赵六数学2149
语文3455
田七数学73148
语文11626
孙八数学48127
语文5294
df.stack(level=0) # 将一级列索引旋转为最内层的行索引
数学语文
一班张三期中673
期末10156
李四期中116111
期末16110
王五期中3821
期末141109
二班赵六期中2134
期末4955
田七期中73116
期末14826
孙八期中4852
期末12794

unstack()

用于将行索引转换为列索引

具有stack()相同的参数,此外还有一个特有的填充参数:

  • fill_value:用于指定在数据重塑过程中填充缺失值的值。如果在转换过程中某些索引组合不存在,则会用 fill_value 指定的值填充这些缺失值。
# 默认level=-1,转换最内层的行索引
#给一个fill_value去填充NaN; 没有指定默认用NaN填充
df.unstack(fill_value=0)
期中...期末
语文数学...语文数学
孙八张三李四王五田七赵六孙八张三李四王五...李四王五田七赵六孙八张三李四王五田七赵六
一班03111210006711638...1101090001011614100
二班520001163448000...00265512700014849

2 rows × 24 columns

# df.unstack(fill_value=0) 将最内层行索引转换为最内层的列索引
# .stack(level=(0, 1)) 将 1 2层的索引转换为列索引
# .unstack(level=0) # 将最外层的行索引转换为内层的列索引
df1 = df.unstack(fill_value=0).stack(level=(0, 1)).unstack(level=0)
df1
孙八张三李四王五田七赵六
一班二班一班二班一班二班一班二班一班二班一班二班
期中数学0486701160380073021
语文0523011102100116034
期末数学0127101016014100148049
语文09456011001090026055

思考:如果我们需要交换一下 列一二级索引,该怎么实现呢?
使用swaplevel函数

swaplevel(0, 1, axis=1)

用于在多层行索引和列索引之间交换级别

  • level0, level1:这两个参数用于指定要交换的级别的位置或名称;在多层索引中,级别从 0 开始计数。

  • axis:这个参数用于指定要在哪个轴上进行级别的交换。对于 DataFrame 对象,axis=0 表示在行索引上进行操作,axis=1 表示在列索引上进行操作。

# 交换列一,二级索引
df1.swaplevel(0, 1, axis=1)
一班二班一班二班一班二班一班二班一班二班一班二班
孙八孙八张三张三李四李四王五王五田七田七赵六赵六
期中数学0486701160380073021
语文0523011102100116034
期末数学0127101016014100148049
语文09456011001090026055

聚合操作

df
期中期末
语文数学语文数学
一班张三36756101
李四11111611016
王五2138109141
二班赵六34215549
田七1167326148
孙八524894127
df_1 = df.loc['一班', '期中'].copy()
df_1
语文数学
张三367
李四111116
王五2138
# 默认axis=0对行聚合, 留下了列, 最后的效果就是求的每一列的和. 
df_1.sum()
"""
语文    135
数学    221
dtype: int64
"""

# axis=1对列聚合,每一行的和. 
df_1.sum(axis=1)
"""
张三     70
李四    227
王五     59
dtype: int64
"""

# 计算一班二班, 各科, 期中期末的平均成绩. 
# axis=0, 意味着对行进行聚合. 
# level=0表示要保留level0, 除此之外的行索引, 就会被聚合掉.
df.sum(level=0, axis=0)
期中期末
语文数学语文数学
一班135221275258
二班202142175324

groupby()

根据指定的条件将数据分组并对每个分组应用相应的操作

  • by:这是最重要的参数,用于指定分组依据的列名、列名列表、Series、索引级别等;用于只有一级索引的聚合。

  • axis:指定分组的方向,axis=0 表示按行分组(默认值),axis=1 表示按列分组。

  • level:如果数据是多层索引的 DataFrame,可以使用 level 参数指定要在哪个级别上进行分组。

  • sort:默认为 True,表示在分组过程中是否对结果进行排序。

  • as_index:默认为 True,表示分组的依据列会变成结果 DataFrame 的索引。如果设置为 False,则不会将分组列设置为索引。

其他参数:group_keys、squeeze、observed 等,用于控制分组的其他行为。

# 默认axix=0按行分组;level=0默认按第0级行索引聚合
df.groupby(level=0).sum()
期中期末
语文数学语文数学
一班135221275258
二班202142175324
# 求一班二班, 期中, 期末总成绩. 
df.groupby(level=0).sum().stack().groupby(level=0).sum()
期中期末
一班356533
二班344499
# 求期末和期中每科目的平均成绩;对列操作. 期中期末要平均掉. 
df.groupby(axis=1, level=1).mean()
数学语文
一班张三84.029.5
李四66.0110.5
王五89.565.0
二班赵六35.044.5
田七110.571.0
孙八87.573.0
# 求期中与期末中每个同学各科目的最高分
df.groupby(axis=1, level=1).max()
数学语文
一班张三10156
李四116111
王五141109
二班赵六4955
田七148116
孙八12794
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值