pandas数据分析给力教程【完整版】(四)

pandas层次化索引

上一篇:pandas数据分析给力教程【完整版】(三)
下一篇:pandas数据分析给力教程【完整版】(五)

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

1. 创建多层行索引

1) 隐式构造

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

data = np.random.randint(0,150, size=(6,6))

index = [['一班', '一班', '一班', '二班', '二班', '二班'], ['张三', '李四', '王五', '赵六', '田七', '孙八']]
columns = [['期中', '期中', '期中', '期末', '期末', '期末'], ['语文', '数学', '英语', '语文', '数学', '英语']]
df = DataFrame(index=index, data=data, columns=columns)
df
期中期末
语文数学英语语文数学英语
一班张三966272932129
李四95120951058049
王五4614624468741
二班赵六168413710610645
田七1148016118738
孙八891002313462123
  • Series也可以创建多层索引
index = [['一班', '一班', '一班', '二班', '二班', '二班'], ['张三', '李四', '王五', '赵六', '田七', '孙八']]
data = np.random.randint(0,150, size=6)
s = Series(data=data, index=index)
s
一班  张三    145
    李四     19
    王五    148
二班  赵六    124
    田七      9
    孙八    114
dtype: int32

2) 显示构造pd.MultiIndex

  • 使用数组
data = np.random.randint(0,150, size=(6,6))

index = pd.MultiIndex.from_arrays([['一班', '一班', '一班', '二班', '二班', '二班'], ['张三', '李四', '王五', '赵六', '田七', '孙八']])
columns = pd.MultiIndex.from_arrays([['期中', '期中', '期中', '期末', '期末', '期末'], ['语文', '数学', '英语', '语文', '数学', '英语']])
df = DataFrame(index=index, data=data, columns=columns)
df
期中期末
语文数学英语语文数学英语
一班张三721381091383294
李四327896842678
王五10677718622134
二班赵六165524164945
田七8157781010089
孙八96137101049869
  • 使用tuple
data = np.random.randint(0,150, size=(6,6))

index = pd.MultiIndex.from_tuples([('一班', '张三'), ('一班', '李四'), ('一班', '王五'), ('二班', '赵六'), ('二班', '田七'), ('二班', '孙八')])
columns = pd.MultiIndex.from_arrays([['期中', '期中', '期中', '期末', '期末', '期末'], ['语文', '数学', '英语', '语文', '数学', '英语']])
df = DataFrame(index=index, data=data, columns=columns)
df
期中期末
语文数学英语语文数学英语
一班张三898241244597
李四11020117295141
王五73343013780145
二班赵六12213210136113
田七29961398297111
孙八8251212625123
  • 使用product

    最简单,推荐使用

data = np.random.randint(0,150, size=(6,6))

index = pd.MultiIndex.from_product([['一班', '二班'], ['张三', '李四', '王五']])
columns = pd.MultiIndex.from_arrays([['期中', '期中', '期中', '期末', '期末', '期末'], ['语文', '数学', '英语', '语文', '数学', '英语']])
df = DataFrame(index=index, data=data, columns=columns)
df
期中期末
语文数学英语语文数学英语
一班张三1423101835637
李四72133749457110
王五962945196137
二班张三14612110081119141
李四2227859232
王五135135161071320

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

练习8:

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

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

2. 多层列索引

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

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

1)Series的操作

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

s
一班  张三    145
    李四     19
    王五    148
二班  赵六    124
    田七      9
    孙八    114
dtype: int32

(1) 索引

原则: 当有多层索引的时候,不要直接索引内层索引.
s.loc['张三']
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

d:\1903\.venv\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
   2889             try:
-> 2890                 return self._engine.get_loc(key)
   2891             except KeyError:


pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()


pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()


pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()


pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()


KeyError: '张三'


During handling of the above exception, another exception occurred:


KeyError                                  Traceback (most recent call last)

<ipython-input-11-73495c5352aa> in <module>
----> 1 s.loc['张三']


d:\1903\.venv\lib\site-packages\pandas\core\indexing.py in __getitem__(self, key)
   1408 
   1409             maybe_callable = com.apply_if_callable(key, self.obj)
-> 1410             return self._getitem_axis(maybe_callable, axis=axis)
   1411 
   1412     def _is_scalar_access(self, key: Tuple):


d:\1903\.venv\lib\site-packages\pandas\core\indexing.py in _getitem_axis(self, key, axis)
   1823         # fall thru to straight lookup
   1824         self._validate_key(key, axis)
-> 1825         return self._get_label(key, axis=axis)
   1826 
   1827 


d:\1903\.venv\lib\site-packages\pandas\core\indexing.py in _get_label(self, label, axis)
    151             # but will fail when the index is not present
    152             # see GH5667
--> 153             return self.obj._xs(label, axis=axis)
    154         elif isinstance(label, tuple) and isinstance(label[axis], slice):
    155             raise IndexingError("no slices here, handle elsewhere")


d:\1903\.venv\lib\site-packages\pandas\core\generic.py in xs(self, key, axis, level, drop_level)
   3734         index = self.index
   3735         if isinstance(index, MultiIndex):
-> 3736             loc, new_index = self.index.get_loc_level(key, drop_level=drop_level)
   3737         else:
   3738             loc = self.index.get_loc(key)


d:\1903\.venv\lib\site-packages\pandas\core\indexes\multi.py in get_loc_level(self, key, level, drop_level)
   2845                 return indexer, maybe_droplevels(indexer, ilevels, drop_level)
   2846         else:
-> 2847             indexer = self._get_level_indexer(key, level=level)
   2848             return indexer, maybe_droplevels(indexer, [level], drop_level)
   2849 


d:\1903\.venv\lib\site-packages\pandas\core\indexes\multi.py in _get_level_indexer(self, key, level, indexer)
   2928         else:
   2929 
-> 2930             code = level_index.get_loc(key)
   2931 
   2932             if level > 0 or self.lexsort_depth == 0:


d:\1903\.venv\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
   2890                 return self._engine.get_loc(key)
   2891             except KeyError:
-> 2892                 return self._engine.get_loc(self._maybe_cast_indexer(key))
   2893         indexer = self.get_indexer([key], method=method, tolerance=tolerance)
   2894         if indexer.ndim > 1 or indexer.size > 1:


pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()


pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()


pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()


pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()


KeyError: '张三'
# 先索引外层索引 推荐写法
s.loc['一班', '张三']
145

(2) 切片

# 不能直接切内层索引
s['张三': '李四']
Series([], dtype: int32)
s['一班': ]
一班  张三    145
    李四     19
    王五    148
二班  赵六    124
    田七      9
    孙八    114
dtype: int32
s.iloc[[0]]
一班  张三    145
dtype: int32
s.iloc[0:3]
一班  张三    145
    李四     19
    王五    148
dtype: int32

2)DataFrame的操作

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

df
期中期末
语文数学英语语文数学英语
一班张三1423101835637
李四72133749457110
王五962945196137
二班张三14612110081119141
李四2227859232
王五135135161071320

行多级索引的索引和切片操作

df.loc['一班',  '张三']
期中  语文    142
    数学      3
    英语    101
期末  语文     83
    数学     56
    英语     37
Name: (一班, 张三), dtype: int32
df.loc['一班': '二班']
期中期末
语文数学英语语文数学英语
一班张三1423101835637
李四72133749457110
王五962945196137
二班张三14612110081119141
李四2227859232
王五135135161071320
df.iloc[[0]]
期中期末
语文数学英语语文数学英语
一班张三1423101835637
df.iloc[0:2]
期中期末
语文数学英语语文数学英语
一班张三1423101835637
李四72133749457110

列多级索引的索引和切片操作

df['期中', '语文']
一班  张三    142
    李四     72
    王五     96
二班  张三    146
    李四      2
    王五    135
Name: (期中, 语文), dtype: int32
df.loc[:, '期中': '期末']
期中期末
语文数学英语语文数学英语
一班张三1423101835637
李四72133749457110
王五962945196137
二班张三14612110081119141
李四2227859232
王五135135161071320
df.iloc[:, 0:4]
期中期末
语文数学英语语文
一班张三142310183
李四721337494
王五96294519
二班张三14612110081
李四222785
王五13513516107

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

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

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

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

练习9:

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

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

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

DataFrame列索引用中括号,行索引用.loc[], 多层索引的时候,不要直接索引内层索引,而要从外层索引往里索引.
df
期中期末
语文数学英语语文数学英语
一班张三1423101835637
李四72133749457110
王五962945196137
二班张三14612110081119141
李四2227859232
王五135135161071320
df.loc['一班', '张三'].loc['期中', '英语'] = np.nan
df.loc[('一班', '张三'), ('期中', '语文')] = np.nan 
df
期中期末
语文数学英语语文数学英语
一班张三NaN3.0NaN83.056.037.0
李四72.0133.074.094.057.0110.0
王五96.029.045.019.06.0137.0
二班张三146.0121.0100.081.0119.0141.0
李四2.022.078.05.092.032.0
王五135.0135.016.0107.0132.00.0
df.dtypes
期中  语文    int32
    数学    int32
    英语    int32
期末  语文    int32
    数学    int32
    英语    int32
dtype: object
# 改变dataframe的类型
df = df.astype(dtype=np.float32)
df.loc['一班', '张三'].loc['期中', '英语'] = np.nan
df
期中期末
语文数学英语语文数学英语
一班张三142.03.0NaN83.056.037.0
李四72.0133.074.094.057.0110.0
王五96.029.045.019.06.0137.0
二班张三146.0121.0100.081.0119.0141.0
李四2.022.078.05.092.032.0
王五135.0135.016.0107.0132.00.0

4. 索引的堆(stack)

  • stack()
  • unstack()
df
期中期末
语文数学英语语文数学英语
一班张三NaN3.0NaN83.056.037.0
李四72.0133.074.094.057.0110.0
王五96.029.045.019.06.0137.0
二班张三146.0121.0100.081.0119.0141.0
李四2.022.078.05.092.032.0
王五135.0135.016.0107.0132.00.0
索引的堆指的就是 多层索引中行索引和列索引的转化
df.stack()
期中期末
一班张三数学3.056.0
英语NaN37.0
语文NaN83.0
李四数学133.057.0
英语74.0110.0
语文72.094.0
王五数学29.06.0
英语45.0137.0
语文96.019.0
二班张三数学121.0119.0
英语100.0141.0
语文146.081.0
李四数学22.092.0
英语78.032.0
语文2.05.0
王五数学135.0132.0
英语16.00.0
语文135.0107.0
df.unstack()
期中期末
语文数学英语语文数学英语
张三李四王五张三李四王五张三李四王五张三李四王五张三李四王五张三李四王五
一班NaN72.096.03.0133.029.0NaN74.045.083.094.019.056.057.06.037.0110.0137.0
二班146.02.0135.0121.022.0135.0100.078.016.081.05.0107.0119.092.0132.0141.032.00.0
df.stack(level=0)
数学英语语文
一班张三期中3.0NaNNaN
期末56.037.083.0
李四期中133.074.072.0
期末57.0110.094.0
王五期中29.045.096.0
期末6.0137.019.0
二班张三期中121.0100.0146.0
期末119.0141.081.0
李四期中22.078.02.0
期末92.032.05.0
王五期中135.016.0135.0
期末132.00.0107.0

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

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

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

练习10:

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

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

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

df
期中期末
语文数学英语语文数学英语
一班张三NaN3.0NaN83.056.037.0
李四72.0133.074.094.057.0110.0
王五96.029.045.019.06.0137.0
二班张三146.0121.0100.081.0119.0141.0
李四2.022.078.05.092.032.0
王五135.0135.016.0107.0132.00.0
df.stack(level=0).unstack(level=0).unstack(level=0)
数学英语语文
一班二班一班二班一班二班
张三李四王五张三李四王五张三李四王五张三李四王五张三李四王五张三李四王五
期中3.0133.029.0121.022.0135.0NaN74.045.0100.078.016.0NaN72.096.0146.02.0135.0
期末56.057.06.0119.092.0132.037.0110.0137.0141.032.00.083.094.019.081.05.0107.0
df.stack().unstack(level=0).unstack(level=0)
期中期末
一班二班一班二班
张三李四王五张三李四王五张三李四王五张三李四王五
数学3.0133.029.0121.022.0135.056.057.06.0119.092.0132.0
英语NaN74.045.0100.078.016.037.0110.0137.0141.032.00.0
语文NaN72.096.0146.02.0135.083.094.019.081.05.0107.0
df
期中期末
语文数学英语语文数学英语
一班张三10432327224
李四3311210677120131
王五7914832429856
二班赵六130852212914478
田七494923120148116
孙八12310711677119111
df.unstack()
df.stack().unstack(level=0, fill_value=0).unstack(level=0)
期中期末
一班二班一班二班
孙八张三李四王五田七赵六孙八张三李四王五田七赵六孙八张三李四王五田七赵六孙八张三李四王五田七赵六
数学031121480010700049850721209800119000148144
英语0210632001160002322024131560011100011678
语文01043379001230004913003277420077000120129

5. 聚合操作

data = np.random.randint(0,150, size=(6,3))

index = ['张三', '李四', '王五', '赵六', '田七', '孙八']
columns = ['语文', '数学', '英语']
df = DataFrame(index=index, data=data, columns=columns)
df
语文数学英语
张三68142135
李四10414053
王五191636
赵六1054863
田七139885
孙八6676136
sum / min /max / mean  / std/ var/ prod/ median / percentile....
df.sum()
语文    501
数学    430
英语    508
dtype: int64
df.sum(axis=1)
张三    345
李四    297
王五     71
赵六    216
田七    232
孙八    278
dtype: int64
df
期中期末
语文数学英语语文数学英语
一班张三898241244597
李四11020117295141
王五73343013780145
二班赵六12213210136113
田七29961398297111
孙八8251212625123
df.sum()
期中  语文    505
    数学    284
    英语    361
期末  语文    408
    数学    388
    英语    730
dtype: int64
df.sum(axis=1)
一班  张三    378
    李四    422
    王五    499
二班  赵六    414
    田七    554
    孙八    409
dtype: int64
# 一班二班,各科成绩的和.
df.sum(axis=0, level=0)
# 先根据axis的值看对行还是对列进行 操作. 再去看level, level等于哪一层 ,哪一层就保留下来.
期中期末
语文数学英语语文数学英语
一班272136188190130383
二班233148173218258347

【注意】

  • 需要指定axis

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

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

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

练习11:

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

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

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

df
期中期末
语文数学英语语文数学英语
一班张三898241244597
李四11020117295141
王五73343013780145
二班赵六12213210136113
田七29961398297111
孙八8251212625123
df.mean(axis=1, level=1)
语文数学英语
一班张三56.563.569.0
李四69.512.5129.0
王五105.057.087.5
二班赵六66.068.572.5
田七55.596.5125.0
孙八104.038.062.5
df.max(axis=1, level=0).iloc[0:2]
期中期末
一班张三8997
李四117141
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值