python学习——pandas层次化索引

1. 创建多层行索引

1) 隐式构造

最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组

  • Series也可以创建多层索引

In [1]:

import numpy as np
import pandas as pd
from pandas import Series,DataFrame

In [3]:

s = Series([1,2,3,4],
           index =[['a','a','b','b'],['期中','期末','期中','期末']] )
s

Out[3]:

a  期中    1
   期末    2
b  期中    3
   期末    4
dtype: int64

In [5]:

df = DataFrame(data = np.random.randint(0,150,size = (6,3)),
               columns = ['语文','数学','python'],
              index = [['Michael','Michael','Lisa','Lisa','Po','Po'],['期中','期末','期中','期末','期中','期末']])
#隐式创建
df

Out[5]:

语文数学python
Michael期中12611114
期末10137145
Lisa期中95138111
期末117605
Po期中13413188
期末5685113

2) 显示构造pd.MultiIndex

  • 使用数组

In [6]:

df1 = DataFrame(data = np.random.randint(0,150,size = (6,3)),
               columns = ["Java",'Html5','Python'],
               index = pd.MultiIndex.from_arrays([['张三','张三','李四','李四','Michael','Michael'],['期中','期末','期中','期末','期中','期末']]))

df1

Out[6]:

JavaHtml5Python
张三期中120119137
期末1011115
李四期中66117121
期末1276970
Michael期中4125128
期末101710
  • 使用tuple

In [7]:

df2 = DataFrame(data = np.random.randint(0,150,size = (6,4)),
               columns = ["Spring",'Summer','Autumn','Winter'],
               index = pd.MultiIndex.from_tuples([('张三','期中'),('张三','期末'),('李四','期中'),('李四','期末'),('Sara','期中'),('Sara','期末')]))

df2

Out[7]:

SpringSummerAutumnWinter
张三期中143841074
期末667271115
李四期中981263742
期末9010590
Sara期中104959328
期末1397143122
  • 使用product

    最简单,推荐使用

In [8]:

df3 = DataFrame(data = np.random.randint(0,150,size = (12,4)),
               columns = ["Spring",'Summer','Autumn','Winter'],
               index = pd.MultiIndex.from_product([['张三','Sara','Lisa'],['middle','end'],list('AB')]))

df3

Out[8]:

SpringSummerAutumnWinter
张三middleA13423530
B61210547
endA1491215056
B17289089
SaramiddleA110648620
B202876136
endA39666278
B128147679
LisamiddleA12511058
B12651133146
endA255710730
B193155120

============================================

练习8:

  1. 创建一个DataFrame,表示出张三李四期中期末各科成绩

============================================

2. 多层列索引

除了行索引index,列索引columns也能用同样的方法创建多层索引

In [16]:

df4 = DataFrame(data = np.random.randint(0,150,size = (4,12)),
               columns = pd.MultiIndex.from_product([['张三','Sara','Lisa'],['middle','end'],list('AB')]),
               index = ["Spring",'Summer','Autumn','Winter'])

df4

Out[16]:

张三SaraLisa
middleendmiddleendmiddleend
ABABABABABAB
Spring109223558381342213450526487
Summer14011713329140125437678113147
Autumn12831146766040345111112964142
Winter111915412894512728425876

3. 多层索引对象的索引与切片操作

1)Series的操作

【重要】对于Series来说,直接中括号[]与使用.loc[]完全一样,因此,推荐使用中括号索引和切片。

多层索引进行切片时,有些汉字,或者英文,不识别,运行异常,并不是代码的问题,自身的bug

(1) 索引

In [17]:

s

Out[17]:

a  期中    1
   期末    2
b  期中    3
   期末    4
dtype: int64

In [19]:

# 第一个参数,多层索引的第一维,第二个参数,多层索引第二维
s['a','期中']

Out[19]:

1

In [22]:

#['a','期中']作为一个参数
s[['a','期中']]

Out[22]:

a  期中    1
   期末    2
dtype: int64

In [24]:

s[['a','b','c']]

Out[24]:

a  期中    1
   期末    2
b  期中    3
   期末    4
dtype: int64

In [15]:

s.loc['李四','期末']

Out[15]:

109

(2) 切片

In [25]:

s['a':'b']

Out[25]:

a  期中    1
   期末    2
b  期中    3
   期末    4
dtype: int64

In [26]:

s.iloc[0:3]

Out[26]:

a  期中    1
   期末    2
b  期中    3
dtype: int64

In [31]:

s2 = Series(data = np.random.randint(0,150,size = 6),index = pd.MultiIndex.from_product([list('ABC'),['e','f']]))
s2

Out[31]:

A  e    136
   f    120
B  e     84
   f     56
C  e    142
   f    101
dtype: int32

In [32]:

s2['A':'C']

Out[32]:

A  e    136
   f    120
B  e     84
   f     56
C  e    142
   f    101
dtype: int32

In [33]:

s2.loc['A':'B']

Out[33]:

A  e    136
   f    120
B  e     84
   f     56
dtype: int32

2)DataFrame的操作

(1) 可以直接使用列名称来进行列索引

对于二维索引,如果包含中文,进行切片时,存在报错bug,不是代码问题

In [44]:

df1.index = pd.MultiIndex.from_product([list('ABC'),['期中','期末']])
df1

Out[44]:

JavaHtml5Python
A期中120119137
期末1011115
B期中66117121
期末1276970
C期中4125128
期末101710

In [46]:

df1['A':'B']

Out[46]:

JavaHtml5Python
A期中120119137
期末1011115
B期中66117121
期末1276970

In [48]:

df1.iloc[0:4]

Out[48]:

JavaHtml5Python
A期中120119137
期末1011115
B期中66117121
期末1276970

(2) 使用行索引需要用loc()等函数

【极其重要】推荐使用loc()函数

注意在对行索引的时候,若一级行索引还有多个,对二级行索引会遇到问题!也就是说,无法直接对二级索引进行索引,必须让二级索引变成一级索引后才能对其进行索引!

In [53]:

df2

Out[53]:

SpringSummerAutumnWinter
张三期中143841074
期末667271115
李四期中981263742
期末9010590
Sara期中104959328
期末1397143122

In [54]:

df2.loc['张三','期中']

Out[54]:

Spring    143
Summer     84
Autumn     10
Winter     74
Name: (张三, 期中), dtype: int32

In [55]:

df2.loc['张三'].loc['期中']

Out[55]:

Spring    143
Summer     84
Autumn     10
Winter     74
Name: 期中, dtype: int32

In [57]:

df2.loc[['张三','李四']]

Out[57]:

SpringSummerAutumnWinter
张三期中143841074
期末667271115
李四期中981263742
期末9010590

============================================

练习9:

  1. 分析比较Series和DataFrame各种索引的方式,熟练掌握.loc()方法

  2. 假设张三再一次在期中考试的时候因为特殊原因放弃英语考试,如何实现?

============================================

4. 索引的堆(stack)

  • stack()
  • unstack()

【小技巧】使用stack()的时候,level等于哪一个,哪一个就消失,出现在行里。

In [58]:

df4

Out[58]:

张三SaraLisa
middleendmiddleendmiddleend
ABABABABABAB
Spring109223558381342213450526487
Summer14011713329140125437678113147
Autumn12831146766040345111112964142
Winter111915412894512728425876

In [60]:

#stack = 堆--->行
#多层索引的列而言0,1,1:从上往下计数
df4.stack()

Out[60]:

LisaSara张三
endmiddleendmiddleendmiddle
SpringA6450223835109
B87521341345822
SummerA113761252913140
B14778431403117
AutumnA641113460146128
B14212951407631
WinterA7421278954111
B65828451291

In [61]:

df4.stack(level=0)

Out[61]:

endmiddle
ABAB
SpringLisa64875052
Sara2213438134
张三355810922
SummerLisa1131477678
Sara1254329140
张三133140117
AutumnLisa64142111129
Sara34516040
张三1467612831
WinterLisa764258
Sara127288945
张三541211191

【小技巧】使用unstack()的时候,level等于哪一个,哪一个就消失,出现在列里。

In [63]:

df2

Out[63]:

SpringSummerAutumnWinter
张三期中143841074
期末667271115
李四期中981263742
期末9010590
Sara期中104959328
期末1397143122

In [62]:

df2.unstack(level=1)

Out[62]:

SpringSummerAutumnWinter
期中期末期中期末期中期末期中期末
Sara1041399579314328122
张三143668472107174115
李四9890126103754290

============================================

练习10:

  1. 使用unstack()将ddd变为两行,分别为期中期末

  2. 使用unstack()将ddd变为四行,分别为四个科目

============================================

5. 聚合操作

【注意】

  • 需要指定axis

  • 【小技巧】和unstack()相反,聚合的时候,axis等于哪一个,哪一个就会进行计算。

所谓的聚合操作:平均数,方差,最大值,最小值……

In [64]:

df1

Out[64]:

JavaHtml5Python
A期中120119137
期末1011115
B期中66117121
期末1276970
C期中4125128
期末101710

In [65]:

#axis=0  进行行间计算
#axis=1 进行列间计算
df1.sum()

Out[65]:

Java      556
Html5     338
Python    581
dtype: int64

In [68]:

df1.sum(axis =1)

Out[68]:

A  期中    376
   期末    217
B  期中    304
   期末    266
C  期中    194
   期末    118
dtype: int64

In [69]:

df1.mean(axis = 1)

Out[69]:

A  期中    125.333333
   期末     72.333333
B  期中    101.333333
   期末     88.666667
C  期中     64.666667
   期末     39.333333
dtype: float64

In [72]:

#数据离散的程度,方差越大数值间差距大
df1.std(axis=1)

Out[72]:

A  期中    10.115994
   期末    62.171805
B  期中    30.664855
   期末    33.201406
C  期中    55.428633
   期末    53.425961
dtype: float64

============================================

练习11:

  1. 计算各个科目期中期末平均成绩

  2. 计算各科目张三李四的最高分

============================================