pandas(三)pandas层次化索引

pandas层次化索引

1. 创建多层行索引

In [1]:
import numpy as np
import pandas as pd
from pandas import Series,DataFrame

1) 隐式构造

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

  • Series也可以创建多层索引
In [2]:
s = Series(data=[100,98,89,90],
           index=[["张三","张三","李四","李四"],["期中","期末","期中","期末"],
                  ["a","b","a","b"]])
s
Out[2]:
张三  期中  a    100
    期末  b     98
李四  期中  a     89
    期末  b     90
dtype: int64
In [3]:
df = DataFrame(data=[100,98,89,90],
           index=[["张三","张三","李四","李四"],["期中","期末","期中","期末"],
                  ["a","b","a","b"]],
           columns = ["python"]
              )
df
Out[3]:
      python
张三 期中 a 100
期末 b 98
李四 期中 a 89
期末 b 90
In [4]:
df1 = DataFrame(data=np.random.randint(0,150,size=(4,4)),
           index=[["张三","张三","李四","李四"],["期中","期末","期中","期末"],
                  ["a","b","a","b"]],
           columns = [["后台","后台","前端","前端"],
                      ["python","java","H5","jQuery"]]
              )
df1
Out[4]:
      后台 前端
      python java H5 jQuery
张三 期中 a 4 108 55 28
期末 b 141 134 27 82
李四 期中 a 56 144 88 65
期末 b 29 100 43 67
In [5]:
df1.index
Out[5]:
MultiIndex(levels=[['张三', '李四'], ['期中', '期末'], ['a', 'b']],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1], [0, 1, 0, 1]])

2) 显示构造pd.MultiIndex

  • 使用数组
In [6]:
# 创建一个多层索引
mindex =pd.MultiIndex.from_arrays([["a",'a','a','b','b','b'],
                     ['一单元',"二单元","三单元",'一单元',"二单元","三单元"]])
mindex
Out[6]:
MultiIndex(levels=[['a', 'b'], ['一单元', '三单元', '二单元']],
           labels=[[0, 0, 0, 1, 1, 1], [0, 2, 1, 0, 2, 1]])
In [7]:
# 用上面的多层索引创建一个df
df = DataFrame(np.random.randint(0,150,size=(6,1)),index=mindex,
               columns=["python"])
df
Out[7]:
    python
a 一单元 89
二单元 9
三单元 128
b 一单元 6
二单元 62
三单元 22
In [8]:
df = DataFrame(np.random.randint(0,150,size=(1,6)),index=["python"],
                  columns=mindex
              )
df
Out[8]:
  a b
  一单元 二单元 三单元 一单元 二单元 三单元
python 141 148 7 80 49 105
  • 使用tuple
In [9]:
mindex = pd.MultiIndex.from_tuples([("河南","郑州"),
                                    ("河南","洛阳"),
                                    ("山东","济南"),
                                    ("河北","石家庄"),
                                    ("北京","天安门"),
                                    ("四川","成都"),
                                    ("江苏","南京")]) 
# 注意:每个元组代表一个行(或列)的索引名,索引名要用元组的元素来体现
mindex
Out[9]:
MultiIndex(levels=[['北京', '四川', '山东', '江苏', '河北', '河南'], ['南京', '天安门', '成都', '洛阳', '济南', '石家庄', '郑州']],
           labels=[[5, 5, 2, 4, 0, 1, 3], [6, 3, 4, 5, 1, 2, 0]])
In [10]:
df = DataFrame(np.random.randint(1,100,size=(7,1)),index=mindex,
               columns=["收入(万)"])
df
Out[10]:
    收入(万)
河南 郑州 75
洛阳 42
山东 济南 11
河北 石家庄 30
北京 天安门 34
四川 成都 1
江苏 南京 2
  • 使用product

    最简单,推荐使用

In [11]:
mindex = pd.MultiIndex.from_product([["河南","山东"],['郑州','济南']])
mindex
Out[11]:
MultiIndex(levels=[['山东', '河南'], ['济南', '郑州']],
           labels=[[1, 1, 0, 0], [1, 0, 1, 0]])
In [12]:
df = DataFrame(np.random.randint(0,100,size=(4,1)),index=mindex)
df
Out[12]:
    0
河南 郑州 98
济南 84
山东 郑州 96
济南 29
In [13]:
sindex = pd.MultiIndex.from_product([["张三","李四"],["期中","期末"],
                                     ["月考一","月考二","月考三"]])
sindex
Out[13]:
MultiIndex(levels=[['张三', '李四'], ['期中', '期末'], ['月考一', '月考三', '月考二']],
           labels=[[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1], [0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1]])
In [14]:
df = DataFrame(np.random.randint(0,150,size=(12,1)),index=sindex)
df
Out[14]:
      0
张三 期中 月考一 66
月考二 126
月考三 132
期末 月考一 115
月考二 58
月考三 29
李四 期中 月考一 10
月考二 1
月考三 65
期末 月考一 123
月考二 106
月考三 108

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

练习8:

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

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

2. 多层列索引

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

In [15]:
# 参照多层行索引
In [ ]:

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

1)Series的操作

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

(1) 索引

In [16]:
s
Out[16]:
张三  期中  a    100
    期末  b     98
李四  期中  a     89
    期末  b     90
dtype: int64
In [17]:
s["张三"]["期末"]["b"]
Out[17]:
98
In [18]:
s["张三","期中","a"]
Out[18]:
100
In [19]:
s[["张三","期中","afdsa","李四","李四"]] 
# 1、如果多个索引里面有无效,则不查找
# 2、如果有重复有效,只查找一次
Out[19]:
张三  期中  a    100
    期末  b     98
李四  期中  a     89
    期末  b     90
dtype: int64
In [ ]:

(2) 切片

In [20]:
s.loc["张三":"李四","期中":"期末"]
Out[20]:
张三  期中  a    100
    期末  b     98
李四  期中  a     89
    期末  b     90
dtype: int64
In [21]:
s.iloc[0:4]
# 【注意】多层索引创建的是显示索引,对隐式索引没有任何影响(隐式索引仍然是代表序列)
Out[21]:
张三  期中  a    100
    期末  b     98
李四  期中  a     89
    期末  b     90
dtype: int64

2)DataFrame的操作

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

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

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

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

In [22]:
sindex = pd.MultiIndex.from_product([["张三","李四"],["期中","期末"],
                                  ["月考一","月考二","月考三"]])
sindex
df = DataFrame(data=np.random.randint(0,150,size=(12,3)),index=sindex,
               columns=["python","java","UI"])
df
Out[22]:
      python java UI
张三 期中 月考一 13 148 80
月考二 5 15 47
月考三 109 70 122
期末 月考一 140 137 57
月考二 74 36 83
月考三 143 54 50
李四 期中 月考一 0 140 53
月考二 147 55 93
月考三 124 43 137
期末 月考一 139 23 55
月考二 103 99 51
月考三 3 3 3
In [23]:
df["python"]["张三"]
Out[23]:
期中  月考一     13
    月考二      5
    月考三    109
期末  月考一    140
    月考二     74
    月考三    143
Name: python, dtype: int32
In [24]:
df[["python"]].loc["张三","期中"]
Out[24]:
  python
月考一 13
月考二 5
月考三 109
In [25]:
df.loc["张三","期中",'月考一']
Out[25]:
python     13
java      148
UI         80
Name: (张三, 期中, 月考一), dtype: int32
In [26]:
df.loc[["张三","期中",'月考一',"李四"]]
Out[26]:
      python java UI
张三 期中 月考一 13 148 80
月考二 5 15 47
月考三 109 70 122
期末 月考一 140 137 57
月考二 74 36 83
月考三 143 54 50
李四 期中 月考一 0 140 53
月考二 147 55 93
月考三 124 43 137
期末 月考一 139 23 55
月考二 103 99 51
月考三 3 3 3
In [27]:
df.loc["张三":"李四"]
Out[27]:
      python java UI
张三 期中 月考一 13 148 80
月考二 5 15 47
月考三 109 70 122
期末 月考一 140 137 57
月考二 74 36 83
月考三 143 54 50
李四 期中 月考一 0 140 53
月考二 147 55 93
月考三 124 43 137
期末 月考一 139 23 55
月考二 103 99 51
月考三 3 3 3
In [28]:
df.iloc[0:4]
Out[28]:
      python java UI
张三 期中 月考一 13 148 80
月考二 5 15 47
月考三 109 70 122
期末 月考一 140 137 57

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

练习9:

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

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

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

In [ ]:

4. 索引的堆(stack)

  • stack()
  • unstack()
In [29]:
df
Out[29]:
      python java UI
张三 期中 月考一 13 148 80
月考二 5 15 47
月考三 109 70 122
期末 月考一 140 137 57
月考二 74 36 83
月考三 143 54 50
李四 期中 月考一 0 140 53
月考二 147 55 93
月考三 124 43 137
期末 月考一 139 23 55
月考二 103 99 51
月考三 3 3 3
In [30]:
df1 = df.unstack(level=2)
df1
Out[30]:
    python java UI
    月考一 月考三 月考二 月考一 月考三 月考二 月考一 月考三 月考二
张三 期中 13 109 5 148 70 15 80 122 47
期末 140 143 74 137 54 36 57 50 83
李四 期中 0 124 147 140 43 55 53 137 93
期末 139 3 103 23 3 99 55 3 51
In [31]:
df1.stack(level=1)
Out[31]:
      python java UI
张三 期中 月考一 13 148 80
月考三 109 70 122
月考二 5 15 47
期末 月考一 140 137 57
月考三 143 54 50
月考二 74 36 83
李四 期中 月考一 0 140 53
月考三 124 43 137
月考二 147 55 93
期末 月考一 139 23 55
月考三 3 3 3
月考二 103 99 51

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

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

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

练习10:

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

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

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

5. 聚合操作

【注意】

  • 需要指定axis

  • 【小技巧】和unstack()相反,聚合的时候,axis等于哪一个,哪一个就保留。

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

In [32]:
df
Out[32]:
      python java UI
张三 期中 月考一 13 148 80
月考二 5 15 47
月考三 109 70 122
期末 月考一 140 137 57
月考二 74 36 83
月考三 143 54 50
李四 期中 月考一 0 140 53
月考二 147 55 93
月考三 124 43 137
期末 月考一 139 23 55
月考二 103 99 51
月考三 3 3 3
In [33]:
df.div(10)
Out[33]:
      python java UI
张三 期中 月考一 1.3 14.8 8.0
月考二 0.5 1.5 4.7
月考三 10.9 7.0 12.2
期末 月考一 14.0 13.7 5.7
月考二 7.4 3.6 8.3
月考三 14.3 5.4 5.0
李四 期中 月考一 0.0 14.0 5.3
月考二 14.7 5.5 9.3
月考三 12.4 4.3 13.7
期末 月考一 13.9 2.3 5.5
月考二 10.3 9.9 5.1
月考三 0.3 0.3 0.3
In [34]:
df.divide(10,axis=1)
Out[34]:
      python java UI
张三 期中 月考一 1.3 14.8 8.0
月考二 0.5 1.5 4.7
月考三 10.9 7.0 12.2
期末 月考一 14.0 13.7 5.7
月考二 7.4 3.6 8.3
月考三 14.3 5.4 5.0
李四 期中 月考一 0.0 14.0 5.3
月考二 14.7 5.5 9.3
月考三 12.4 4.3 13.7
期末 月考一 13.9 2.3 5.5
月考二 10.3 9.9 5.1
月考三 0.3 0.3 0.3
In [35]:
df.sum(axis=1)
Out[35]:
张三  期中  月考一    241
        月考二     67
        月考三    301
    期末  月考一    334
        月考二    193
        月考三    247
李四  期中  月考一    193
        月考二    295
        月考三    304
    期末  月考一    217
        月考二    253
        月考三      9
dtype: int64
In [36]:
df.std(axis=0)
Out[36]:
python    61.193186
java      50.792731
UI        36.239419
dtype: float64
In [37]:
df.where(df>50,other=0) # 这个函数是根据条件来过滤
Out[37]:
      python java UI
张三 期中 月考一 0 148 80
月考二 0 0 0
月考三 109 70 122
期末 月考一 140 137 57
月考二 74 0 83
月考三 143 54 0
李四 期中 月考一 0 140 53
月考二 147 55 93
月考三 124 0 137
期末 月考一 139 0 55
月考二 103 99 51
月考三 0 0 0

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

练习11:

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

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

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

In [ ]:

猜你喜欢

转载自blog.csdn.net/qq_29784441/article/details/80861399