• Pandas系列(十八)- 多级索引


    多级索引

    多级索引(也称层次化索引)是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。
    实质上,单级索引对应Index对象,多级索引对应MultiIndex对象。

    一、Series对象的多级索引

    • 多级索引Series对象的创建
    import pandas as pd
    import numpy as np
    
    se1=pd.Series(np.random.randn(4),index=[list("aabb"),[1,2,1,2]])
    se1
    Out[6]: 
    a  1    0.357171
       2    0.084055
    b  1   -0.678752
       2    0.132007
    dtype: float64
    • 子集的选取
    se1['a']
    Out[7]: 
    1    0.357171
    2    0.084055
    dtype: float64
    se1['a':'b']
    Out[8]: 
    a  1    0.357171
       2    0.084055
    b  1   -0.678752
       2    0.132007
    dtype: float64 
    • 内层选取

    se1[:, 1]
    Out[9]: 
    a    0.357171
    b   -0.678752
    dtype: float64
    se1[:, 2]
    Out[10]: 
    a    0.084055
    b    0.132007
    dtype: float64

    二、DataFrame对象的多级索引

    • 1. 创建多层行索引
    • 隐式构造
    import numpy as np
    df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=[['Michal', 'Michal', 'Kobe','Kobe', 'James', 'James'],['Mid','End', 'Mid', 'End','Mid', 'End']])
    df
    Out[25]: 
                 语文   数学  Python
    Michal Mid  100   43      73
           End   11   18      60
    Kobe   Mid  104   66      54
           End   30  120     134
    James  Mid  135   77      56
           End   45  127      63

      显式构造

    • 使用数组
    df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_arrays([['Michal', 'Michal', 'Kobe','Kobe', 'James', 'James'],['Mid','End', 'Mid', 'End','Mid', 'End']]))
    df
    Out[27]: 
                语文   数学  Python
    Michal Mid  56   46     104
           End  83   57      95
    Kobe   Mid  48   94      45
           End  22   99      49
    James  Mid  65   66      91
           End  69  101      84  
    • 使用元组
    df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_tuples([('Michal','期中'), ('Michal','期末'), ('Kobe','期中'), ('Kobe','期末'), ('James','期中'), ('James','期末')]))
    df
    Out[29]: 
                语文   数学  Python
    Michal 期中   10  107      48
           期末  113   49     147
    Kobe   期中  116  138      29
           期末    7   64      53
    James  期中    1   30      21
           期末   70   76     108
    • 使用product
    df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_product([['Michal','Kobe','James'],['Mid','End']]))
    df
    Out[31]: 
                语文   数学  Python
    Michal Mid  85   89      17
           End  21    4      23
    Kobe   Mid  54  117     108
           End  37   20      79
    James  Mid  56   47      82
           End  45   57     126

        2. 多层列索引

    df = pd.DataFrame(np.random.randint(0, 150, size=(3,6)), index=['语文', '数学', 'Python'], columns=pd.MultiIndex.from_product([['Michal','Kobe','James'],['Mid','End']]))
    df
    Out[34]: 
           Michal     Kobe      James     
              Mid End  Mid  End   Mid  End
    语文         74  84   76  142    36   87
    数学         44  90   57  143    78   68
    Python     79  46  120   47   128  145
    

        3. 索引赋值,设置名称和交换

    df1=pd.DataFrame(np.arange(12).reshape(4,3),index=[list("AABB"),[1,2,1,2]],columns=[list("XXY"),[10,11,10]])
    df1
    Out[11]: 
         X       Y
        10  11  10
    A 1  0   1   2
      2  3   4   5
    B 1  6   7   8
      2  9  10  11
    • 赋名
    df1.columns.names=['XY','sum']
    df1.index.names=['AB','num']
    df1
    Out[12]: 
    XY      X       Y
    sum    10  11  10
    AB num           
    A  1    0   1   2
       2    3   4   5
    B  1    6   7   8
       2    9  10  11
    • 创建MultiIndex对象再作为索引
    df1.index=pd.MultiIndex.from_arrays([list("AABB"),[3,4,3,4]],names=["AB","num"])
    df1
    Out[13]: 
    XY      X       Y
    sum    10  11  10
    AB num           
    A  3    0   1   2
       4    3   4   5
    B  3    6   7   8
       4    9  10  11
    • 可以对各级索引进行互换
    df1.swaplevel('AB','num')
    Out[14]: 
    XY      X       Y
    sum    10  11  10
    num AB           
    3   A   0   1   2
    4   A   3   4   5
    3   B   6   7   8
    4   B   9  10  11

        4. 获取索引值

    df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_product([['Michal','Kobe','James'],['Mid','End']]))
    df
    Out[38]: 
                 语文   数学  Python
    Michal Mid   65  134      85
           End   94   91      48
    Kobe   Mid  118  142     141
           End    2   32     106
    James  Mid   29   11     127
           End   16   93      99
    df.index
    Out[39]: 
    MultiIndex([('Michal', 'Mid'),
                ('Michal', 'End'),
                (  'Kobe', 'Mid'),
                (  'Kobe', 'End'),
                ( 'James', 'Mid'),
                ( 'James', 'End')],
               )
    
    # loc获取
    df.loc['James', :]
    Out[42]: 
         语文  数学  Python
    Mid  29  11     127
    End  16  93      99
    df[df.index.get_level_values(0) == 'Michal']
    Out[45]: 
                语文   数学  Python
    Michal Mid  65  134      85
           End  94   91      48
    df[df.index.get_level_values(1) == 'Mid']
    Out[46]: 
                 语文   数学  Python
    Michal Mid   65  134      85
    Kobe   Mid  118  142     141
    James  Mid   29   11     127
    df.loc[('James', 'Mid'), :]
    Out[41]: 
    语文         29
    数学         11
    Python    127
    Name: (James, Mid), dtype: int32

     三、案例:考试数据分析

    试题:
    • 1. 计算每个学生的总成绩

    • 2. 计算每个学生各学期的总成绩

    • 3. 各门课程平均成绩

    • 4. 各学期大于本课程平均成绩的学生姓名及成绩

       整理数据

    • 读取数据
    import pandas as pd
    exam_data = pd.read_excel('试题.xlsx', sheet_name='试题数据')
    exam_data
    Out[3]: 
         姓名    课程  学期  成绩
    0   王大伟  大学英语   1  92
    1   王大伟  大学英语   2  85
    2   王大伟  大学英语   3  83
    3   王大伟  大学英语   4  90
    4   王大伟  高等数学   1  91
    5   王大伟  高等数学   2  86
    6   王大伟  高等数学   3  98
    7   王大伟  高等数学   4  84
    8   王大伟  大学体育   1  78
    9   王大伟  大学体育   2  91
    
    • 设置索引
    # 读取时设置
    exam_data = pd.read_excel('试题.xlsx', sheet_name='试题数据', index_col=[0, 1])
    exam_data
    Out[5]: 
              学期  成绩
    姓名  课程          
    王大伟 大学英语   1  92
        大学英语   2  85
        大学英语   3  83
        大学英语   4  90
        高等数学   1  91
        高等数学   2  86
        高等数学   3  98
        高等数学   4  84
        大学体育   1  78
        大学体育   2  91
        大学体育   3  80
        大学体育   4  90
    孙力  大学英语   1  87
        大学英语   2  79
        大学英语   3  93
        大学英语   4  78
        高等数学   1  87
        高等数学   2  93
        高等数学   3  85
        高等数学   4  89
        大学体育   1  77
        大学体育   2  83
        大学体育   3  99
        大学体育   4  88
    张明  大学英语   1  88
        大学英语   2  94
        大学英语   3  96
        大学英语   4  87
        高等数学   1  97
        高等数学   2  89
        高等数学   3  94
        高等数学   4  86
        大学体育   1  87
        大学体育   2  85
        大学体育   3  86
        大学体育   4  92
    
    # 设置索引列
    exam_data.set_index(keys=['姓名', '课程'])
    Out[21]: 
              学期  成绩
    姓名  课程          
    王大伟 大学英语   1  92
        大学英语   2  85
        大学英语   3  83
        大学英语   4  90
        高等数学   1  91
        高等数学   2  86
        高等数学   3  98
        高等数学   4  84
        大学体育   1  78
        大学体育   2  91
        大学体育   3  80
        大学体育   4  90
    孙力  大学英语   1  87
        大学英语   2  79
        大学英语   3  93
        大学英语   4  78
        高等数学   1  87
        高等数学   2  93
        高等数学   3  85
        高等数学   4  89
        大学体育   1  77
        大学体育   2  83
        大学体育   3  99
        大学体育   4  88
    张明  大学英语   1  88
        大学英语   2  94
        大学英语   3  96
        大学英语   4  87
        高等数学   1  97
        高等数学   2  89
        高等数学   3  94
        高等数学   4  86
        大学体育   1  87
        大学体育   2  85
        大学体育   3  86
        大学体育   4  92

    当然,这里我们不需要对其设置索引

    • 1. 计算每个学生总成绩
    exam_data = pd.read_excel('试题.xlsx', sheet_name='试题数据')
    # 1. 计算每个学生总成绩
    student_total_score = exam_data.groupby(by=['姓名']).agg(
        {'成绩': sum}).rename(columns={'成绩': '总成绩'})
    print('1. 学生总成绩:
    ', student_total_score)
    1. 学生总成绩:
           总成绩
    姓名       
    孙力   1038
    张明   1081
    王大伟  1048
    
    • 2. 每个学生各学期的总成绩
    # 2. 每个学生各学期的总成绩
    student_semester_total = exam_data.groupby(by=['姓名', '学期']).agg(
        {'成绩': sum}).rename({'成绩': ' 总成绩'})
    print('
    2. 学生每个学期总成绩:
    ', student_semester_total)
    2. 学生每个学期总成绩:
              成绩
    姓名  学期     
    孙力  1   251
        2   255
        3   277
        4   255
    张明  1   272
        2   268
        3   276
        4   265
    王大伟 1   261
        2   262
        3   261
        4   264
    

      3. 各门课程平均成绩

    # 3. 各门课程平均成绩
    course_avg_score = exam_data.groupby(by=['课程'])['成绩'].mean()
    print('
    3. 各门课程平均成绩:
    ', course_avg_score)
    3. 各门课程平均成绩:
     课程
    大学体育    86.333333
    大学英语    87.666667
    高等数学    89.916667
    Name: 成绩, dtype: float64
    
    • 4. 各学期大于本课程平均成绩的学生姓名及成绩
    def judge_score(row):
        return row['成绩'] > course_avg_score[row['课程']]
    greater_than_avg_student = exam_data[exam_data.apply(judge_score, axis=1)].set_index(keys=['姓名', '课程'])
    print('
    4. 各学期大于本课程平均成绩的学生姓名及成绩: 
    ', greater_than_avg_student)
    4. 各学期大于本课程平均成绩的学生姓名及成绩: 
               学期  成绩
    姓名  课程          
    王大伟 大学英语   1  92
        大学英语   4  90
        高等数学   1  91
        高等数学   3  98
        大学体育   2  91
        大学体育   4  90
    孙力  大学英语   3  93
        高等数学   2  93
        大学体育   3  99
        大学体育   4  88
    张明  大学英语   1  88
        大学英语   2  94
        大学英语   3  96
        高等数学   1  97
        高等数学   3  94
        大学体育   1  87
        大学体育   4  92
    •  将结果输出到文件
    # 输出文件
    with pd.ExcelWriter(path="结果.xlsx") as writer:
        exam_data.to_excel(excel_writer=writer, sheet_name='试题数据', encoding='utf-8', index=False)
        student_total_score.to_excel(excel_writer=writer, sheet_name='学生总成绩', encoding='utf-8')
        student_semester_total.to_excel(excel_writer=writer, sheet_name='每个学生各学期总成绩', encoding='utf-8')
        course_avg_score.to_excel(excel_writer=writer, sheet_name='各门课程平均成绩', encoding='utf-8')
        greater_than_avg_student.to_excel(excel_writer=writer, sheet_name='各学期大于本课程平均成绩的学生姓名及成绩', encoding='utf-8')
        writer.save()
    
  • 相关阅读:
    PHP xml_get_current_column_number() 函数
    PHP xml_get_current_byte_index() 函数
    PHP xml_error_string() 函数
    PHP utf8_encode() 函数
    PHP utf8_decode() 函数
    MySQL 资料库概论与MySQL 安装
    SEO之网站关键词的优化 :首页,内页关键字,长尾关键字
    前端开发chrome console的使用 :评估表达式 – Break易站
    chrome console的使用 : 异常和错误的处理 – Break易站
    SEO的基本概念 和 提交SITEMAP到搜索引擎
  • 原文地址:https://www.cnblogs.com/zhangyafei/p/12114521.html
Copyright © 2020-2023  润新知