pandas索引(loc,[],iloc,query,at/iat,cut,set_index,sort_index,reset_index,where,drop_duplicates...)

快速浏览

    • pandas简单介绍和本文说明
    • 一、单级索引
      • 1. 读取csv格式的新发现
      • 2. loc方法、iloc方法、[ ]操作符
        • (a)loc方法
        • (b)iloc方法
        • (c) [ ]操作符
      • 3.布尔索引
      • 4. 快速标量索引
      • 5. 区间索引
    • 二、多级索引
      • 1.创建多级索引
      • 2.多层索引切片
      • 3.多层索引中的slice对象
      • 4.索引层的交换
        • (a)swaplevel方法(两层交换)
        • (b)reorder_levels方法(多层交换)
    • 三、索引设定
      • 1.index_col参数
      • 2.reindex和reindex_like
      • 3.set_index和reset_index
      • 4.rename_axis和rename
    • 四、常用索引型函数
      • 1.where函数
      • 2.mask函数
      • 3.query函数
    • 五、重复元素处理
      • 1.duplicated方法
      • 2.drop_duplicates方法
    • 六、抽样函数
    • 七、问题与练习(附解答)
      • 1. 问题
      • 2. 练习
    • Reference

pandas简单介绍和本文说明

pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。
pandas is a fast, powerful, flexible and easy to use open source data analysis and manipulation tool,built on top of the Python programming language.

进入官网可以看到现在最新的版本是1.0.3,之后代码也就使用1.0.3的pd咯。此系列主要参考Pandas官方文档和由Datawhale主办的一期Joyful-Pandas,结合自己使用pandas的一些体会进行扩展,最后还有个人对问题和练习的解答。使用到的数据集可以在此下载。
pandas索引(loc,[],iloc,query,at/iat,cut,set_index,sort_index,reset_index,where,drop_duplicates...)_第1张图片

#从清华镜像拉装1.0.3版本的Pandas
!pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas==1.0.3
import pandas as pd
#查看Pandas版本
pd.__version__
'1.0.3'

一般使用python安装库,会用到pip install libName。这会在Python的官方源pypi.python.org/pypi 下载,有时会因为超时会抛异常无法下载成功。所以可以选择一些比较稳定速度比较快的国内镜像来下载python库。

这里选择用清华的镜像是因为大多数时候直接pip install 一个库会比较慢,国内常用阿里、豆瓣、中科大的镜像网址如下,可以自行选择替换。

https://mirrors.aliyun.com/pypi/simple/
https://pypi.douban.com/simple
https://mirrors.ustc.edu.cn/pypi/web/simple

本文的精华总结:行用loc,列用[ ],位置用iloc,条件用bool/query,标量用at/iat

一、单级索引

1. 读取csv格式的新发现

df1 = pd.read_csv('work/table.csv',index_col='ID')
print(df1.head(3))
df2 = pd.read_csv('work/table.csv')
print(df2.head(3))

区别是一个以ID为索引,一个默认自动生成从0开始的索引。

     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1103    S_1   C_1      M  street_2     186      82  87.2      B+
  School Class    ID Gender   Address  Height  Weight  Math Physics
0    S_1   C_1  1101      M  street_1     173      63  34.0      A+
1    S_1   C_1  1102      F  street_2     192      73  32.5      B+
2    S_1   C_1  1103      M  street_2     186      82  87.2      B+

2. loc方法、iloc方法、[ ]操作符

最常用的索引方法可能就是这三类,其中iloc表示位置索引,loc表示标签索引,[]也具有很大的便利性,各有特点。

(a)loc方法

注意:所有在loc中使用的切片全部包含右端点!

df = pd.read_csv('work/table.csv',index_col='ID')
print('在loc中使用的切片全部包含右端点')
print(df.loc[1103])
print('单行索引')
print(df.loc[[1103]])
print('多行索引')
print(df.loc[[1102,2304]])
print('逆序多行索引')
print(df.loc[2402::-1].head(3))
print('正序多行索引')
print(df.loc[2402::1].head(3))
在loc中使用的切片全部包含右端点
School          S_1
Class           C_1
Gender            M
Address    street_2
Height          186
Weight           82
Math           87.2
Physics          B+
Name: 1103, dtype: object
单行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1103    S_1   C_1      M  street_2     186      82  87.2      B+
多行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
2304    S_2   C_3      F  street_6     164      81  95.5      A-
逆序多行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
2402    S_2   C_4      M  street_7     166      82  48.7       B
2401    S_2   C_4      F  street_2     192      62  45.3       A
2305    S_2   C_3      M  street_4     187      73  48.9       B
正序多行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
2402    S_2   C_4      M  street_7     166      82  48.7       B
2403    S_2   C_4      F  street_6     158      60  59.7      B+
2404    S_2   C_4      F  street_2     160      84  67.7       B
df.loc[:,'Height'].head()
df.loc[:,['Height','Math']].head()
df.loc[:,'Height':'Math'].head()
print('列索引和行索引其实可以看做只使用了联合索引部分功能')
print(df.loc[1102:2401:3,'Height':'Math'].head())
列索引和行索引其实可以看做只使用了联合索引部分功能
      Height  Weight  Math
ID                        
1102     192      73  32.5
1105     159      64  84.8
1203     160      53  58.8
1301     161      68  31.5
1304     195      70  85.2
print(df.loc[lambda x:x['Gender']=='M'].head())
print('loc中使用的函数,传入参数就是前面的df')
def f(x):
    return [1102,2304]
print(df.loc[f])
print('与之前"df.loc[[1102,2304]]"一样')

print('本质上说,loc中能传入的只有布尔列表和索引子集构成的列表')
print(df.loc[df['Address'].isin(['street_7','street_4'])].head(3))
print(df.loc[[True if i[-1]=='4' or i[-1]=='7' else False for i in df['Address'].values]].head(3))
print('都是选择"Address"为4或7的')
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1103    S_1   C_1      M  street_2     186      82  87.2      B+
1201    S_1   C_2      M  street_5     188      68  97.0      A-
1203    S_1   C_2      M  street_6     160      53  58.8      A+
1301    S_1   C_3      M  street_4     161      68  31.5      B+
loc中使用的函数,传入参数就是前面的df
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
2304    S_2   C_3      F  street_6     164      81  95.5      A-
与之前"df.loc[[1102,2304]]"一样
本质上说,loc中能传入的只有布尔列表和索引子集构成的列表
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1105    S_1   C_1      F  street_4     159      64  84.8      B+
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1301    S_1   C_3      M  street_4     161      68  31.5      B+
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1105    S_1   C_1      F  street_4     159      64  84.8      B+
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1301    S_1   C_3      M  street_4     161      68  31.5      B+
都是选择"Address"为4或7的

小节:本质上说,loc中能传入的只有布尔列表和索引子集构成的列表,只要把握这个原则就很容易理解上面那些操作。

(b)iloc方法

注意与loc不同,切片右端点不包含,接收的参数只能为整数或整数列表,不能使用布尔索引

df = pd.read_csv('work/table.csv',index_col='ID')
print('在iloc中使用的切片不包含右端点,接收的参数只能为整数或整数列表')
print(df.iloc[3])
print('单行索引')
print(df.iloc[[3]])
print('多行索引')
print(df.iloc[3:5])
print('多列索引')
print(df.iloc[:,7::-2].head())
print('列索引和行索引其实可以看做只使用了联合索引部分功能')
print(df.iloc[3::4,7::-2].head())
#df.iloc[lambda x:[3]].head()
#函数式索引
在iloc中使用的切片不包含右端点,接收的参数只能为整数或整数列表
School          S_1
Class           C_1
Gender            F
Address    street_2
Height          167
Weight           81
Math           80.4
Physics          B-
Name: 1104, dtype: object
单行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1104    S_1   C_1      F  street_2     167      81  80.4      B-
多行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+
多列索引
     Physics  Weight   Address Class
ID                                  
1101      A+      63  street_1   C_1
1102      B+      73  street_2   C_1
1103      B+      82  street_2   C_1
1104      B-      81  street_2   C_1
1105      B+      64  street_4   C_1
列索引和行索引其实可以看做只使用了联合索引部分功能
     Physics  Weight   Address Class
ID                                  
1104      B-      81  street_2   C_1
1203      A+      53  street_6   C_2
1302      A-      57  street_1   C_3
2101       C      84  street_7   C_1
2105       A      81  street_4   C_1

(c) [ ]操作符

如果不想陷入困境,请不要在行索引为浮点时使用[ ]操作符,因为在Series中的浮点[]并不是进行位置比较,而是值比较,非常特殊。以下为例子:

s=pd.Series([1,3,5,7],index=[1,2,3,4])
print(s)
print(s[2:])#切片是位置索引
s=pd.Series([1,3,5,7],index=[1.1,2.1,3.1,4.4])
print(s)
print(s[2.1:])#切片是位置索引
print(s[2:])#浮点数下整数切片是元素索引,第二个元素
print(s[2.1])
1    1
2    3
3    5
4    7
dtype: int64
3    5
4    7
dtype: int64
1.1    1
2.1    3
3.1    5
4.4    7
dtype: int64
2.1    3
3.1    5
4.4    7
dtype: int64
2.1    3
3.1    5
4.4    7
dtype: int64
3

Series的[ ]操作

s = pd.Series(df['Math'],index=df.index)
print('单元素索引')
print(s[1101])#使用的是索引标签
print('多行索引')
print(s[0:4])#使用的是绝对位置的整数切片,与元素无关
print('函数式索引')
print(s[lambda x: x.index[16::-6]])
#注意使用lambda函数时,直接切片(如:s[lambda x: 16::-6])就报错,此时使用的不是绝对位置切片,而是元素切片,非常易错
print('布尔索引')
print(s[s>80])
单元素索引
34.0
多行索引
ID
1101    34.0
1102    32.5
1103    87.2
1104    80.4
Name: Math, dtype: float64
函数式索引
ID
2102    50.6
1301    31.5
1105    84.8
Name: Math, dtype: float64
布尔索引
ID
1103    87.2
1104    80.4
1105    84.8
1201    97.0
1302    87.7
1304    85.2
2101    83.3
2205    85.4
2304    95.5
Name: Math, dtype: float64

DataFrame的[ ]操作

print('单行索引')
print(df[1:2])
#这里非常容易写成df[1102],会报错
#同Series使用了绝对位置切片
#如果想要获得某一个元素,可用如下get_loc方法:
row = df.index.get_loc(1102)
print(df[row:row+1])
print('多行索引')
#用切片,如果是选取指定的某几行,推荐使用loc,否则很可能报错
print(df[3:5])
print('单列索引')
print(df['School'].head())
print('多列索引')
print(df[['School','Math']].head())
print('函数式索引')
print(df[lambda x:['Math','Physics']].head())
print('布尔索引')
print(df[df['Gender']=='F'].head())
单行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
多行索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+
单列索引
ID
1101    S_1
1102    S_1
1103    S_1
1104    S_1
1105    S_1
Name: School, dtype: object
多列索引
     School  Math
ID               
1101    S_1  34.0
1102    S_1  32.5
1103    S_1  87.2
1104    S_1  80.4
1105    S_1  84.8
函数式索引
      Math Physics
ID                
1101  34.0      A+
1102  32.5      B+
1103  87.2      B+
1104  80.4      B-
1105  84.8      B+
布尔索引
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1204    S_1   C_2      F  street_5     162      63  33.8       B

小结:一般来说,[ ]操作符常用于列选择或布尔选择,尽量避免行的选择

3.布尔索引

print("布尔符号:'&','|','~':分别代表和and,或or,取反not")
print(df[(df['Gender']=='F')&(df['Address']=='street_2')].head())
print(df[(df['Math']>85)|(df['Address']=='street_7')].head())
print("'Math'>75且'Address'为'street_1'的不要")
print(df[~((df['Math']>75)|(df['Address']=='street_1'))].head())
print('loc和[ ]中相应位置都能使用布尔列表选择')
print(df.loc[df['Math']>60,(df[:8]['Address']=='street_6').values].head())
#如果不加values就会索引对齐发生错误,pandas中的索引对齐是一个重要特征,很多时候非常使用
#但是若不加以留意,就会埋下隐患
布尔符号:'&','|','~':分别代表和and,或or,取反not
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
2401    S_2   C_4      F  street_2     192      62  45.3       A
2404    S_2   C_4      F  street_2     160      84  67.7       B
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1103    S_1   C_1      M  street_2     186      82  87.2      B+
1201    S_1   C_2      M  street_5     188      68  97.0      A-
1302    S_1   C_3      F  street_1     175      57  87.7      A-
1303    S_1   C_3      M  street_7     188      82  49.7       B
1304    S_1   C_3      M  street_2     195      70  85.2       A
'Math'>75且'Address'为'street_1'的不要
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1203    S_1   C_2      M  street_6     160      53  58.8      A+
1204    S_1   C_2      F  street_5     162      63  33.8       B
1205    S_1   C_2      F  street_6     167      63  68.4      B-
loc和[ ]中相应位置都能使用布尔列表选择
     Physics
ID          
1103      B+
1104      B-
1105      B+
1201      A-
1202      B-
print(' isin方法')
print(df[df['Address'].isin(['street_1','street_4'])&df['Physics'].isin(['A','A+'])])
print(' 上面也可以用字典方式写:')
print(df[df[['Address','Physics']].isin({'Address':['street_1','street_4'],'Physics':['A','A+']}).all(1)])
#all与&的思路是类似的,其中的1代表按照跨列方向判断是否全为True
 isin方法
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
2105    S_2   C_1      M  street_4     170      81  34.2       A
2203    S_2   C_2      M  street_4     155      91  73.8      A+
 上面也可以用字典方式写:
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
2105    S_2   C_1      M  street_4     170      81  34.2       A
2203    S_2   C_2      M  street_4     155      91  73.8      A+

4. 快速标量索引

当只需要取一个元素时,at和iat方法能够提供更快的实现

display(df.at[1101,'School'])
display(df.loc[1101,'School'])
display(df.iat[0,0])
display(df.iloc[0,0])
#可对比时间
%timeit df.at[1101,'School']
%timeit df.loc[1101,'School']
%timeit df.iat[0,0]
%timeit df.iloc[0,0]
'S_1'
'S_1'
'S_1'
'S_1'
3.82 µs ± 6.69 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
6.38 µs ± 13.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
4.41 µs ± 7.33 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
6.7 µs ± 4.79 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

5. 区间索引

此处介绍并不是说只能在单级索引中使用区间索引,只是作为一种特殊类型的索引方式,在此处先行介绍。

print("a)利用interval_range方法")
print(pd.interval_range(start=0,end=5))
#closed参数可选'left''right''both''neither',默认左开右闭'right'
print(pd.interval_range(start=0,end=5,closed='neither'))
print(pd.interval_range(start=0,periods=5,freq=5,closed='both'))
#periods参数控制区间个数,freq控制步长
print("(b)利用cut将数值列转为区间为元素的分类变量,例如统计数学成绩的区间情况")
math_interval = pd.cut(df['Math'],bins=[0,40,60,80,100])
print('注意,如果没有类型转换,此时并不是区间类型,而是category类型')
print(math_interval.head())
print("(c)区间索引的选取")
df_i = df.join(math_interval,rsuffix='_interval')[['Math','Math_interval']].reset_index().set_index('Math_interval')
#lsuffix 和 rsuffix分别指定左表的后缀和右表的后缀;suffixes给每个表的重复列名增加后缀
#reset_index可以还原索引,重新变为默认的整型索引;通过set_index方法,可以设置单索引和复合索引
print(df_i.head())
print("包含该值就会被选中")
print(df_i.loc[65].head(10))
print(df_i.loc[[65,90]].head(10))
print("如果想要选取某个区间,先要把分类变量转为区间变量,再使用overlap方法")
#df_i.loc[pd.Interval(70,75)].head() 报错
print(df_i[df_i.index.astype('interval').overlaps(pd.Interval(70, 85))].head())
## overlaps 判断两个区间是否重复,pd.Interval(70, 85)区间(70, 85]
a)利用interval_range方法
IntervalIndex([(0, 1], (1, 2], (2, 3], (3, 4], (4, 5]],
              closed='right',
              dtype='interval[int64]')
IntervalIndex([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)],
              closed='neither',
              dtype='interval[int64]')
IntervalIndex([[0, 5], [5, 10], [10, 15], [15, 20], [20, 25]],
              closed='both',
              dtype='interval[int64]')
(b)利用cut将数值列转为区间为元素的分类变量,例如统计数学成绩的区间情况
注意,如果没有类型转换,此时并不是区间类型,而是category类型
ID
1101      (0, 40]
1102      (0, 40]
1103    (80, 100]
1104    (80, 100]
1105    (80, 100]
Name: Math, dtype: category
Categories (4, interval[int64]): [(0, 40] < (40, 60] < (60, 80] < (80, 100]]
(c)区间索引的选取
                 ID  Math
Math_interval            
(0, 40]        1101  34.0
(0, 40]        1102  32.5
(80, 100]      1103  87.2
(80, 100]      1104  80.4
(80, 100]      1105  84.8
包含该值就会被选中
                 ID  Math
Math_interval            
(60, 80]       1202  63.5
(60, 80]       1205  68.4
(60, 80]       1305  61.7
(60, 80]       2104  72.2
(60, 80]       2202  68.5
(60, 80]       2203  73.8
(60, 80]       2301  72.3
(60, 80]       2303  65.9
(60, 80]       2404  67.7
                 ID  Math
Math_interval            
(60, 80]       1202  63.5
(60, 80]       1205  68.4
(60, 80]       1305  61.7
(60, 80]       2104  72.2
(60, 80]       2202  68.5
(60, 80]       2203  73.8
(60, 80]       2301  72.3
(60, 80]       2303  65.9
(60, 80]       2404  67.7
(80, 100]      1103  87.2
如果想要选取某个区间,先要把分类变量转为区间变量,再使用overlap方法
                 ID  Math
Math_interval            
(80, 100]      1103  87.2
(80, 100]      1104  80.4
(80, 100]      1105  84.8
(80, 100]      1201  97.0
(60, 80]       1202  63.5

Interval 有三种对集合区间的操作方法,分别是 join,overlaps,adjacent_to ,join 合并两个连续的区间集合,overlaps 判断两个区间是否重复,adjacent_to 判断区间是否相邻比重复。

二、多级索引

1.创建多级索引

(a)tuples\zip\array通过from_tuples

print('直接创建元组')
tuples = [('A','a'),('A','b'),('B','a'),('B','b')]
mul_index = pd.MultiIndex.from_tuples(tuples, names=('Upper', 'Lower'))
print(mul_index)
print(pd.DataFrame({'Score':['perfect','good','fair','bad']},index=mul_index))
直接创建元组
MultiIndex([('A', 'a'),
            ('A', 'b'),
            ('B', 'a'),
            ('B', 'b')],
           names=['Upper', 'Lower'])
               Score
Upper Lower         
A     a      perfect
      b         good
B     a         fair
      b          bad
print('利用zip创建元组')
L1 = list('AABB')
L2 = list('abab')
tuples = list(zip(L1,L2))
mul_index = pd.MultiIndex.from_tuples(tuples, names=('Upper', 'Lower'))
print(pd.DataFrame({'Score':['perfect','good','fair','bad']},index=mul_index))
print('利用array创建元组')
arrays = [['A','a'],['A','b'],['B','a'],['B','b']]
mul_index = pd.MultiIndex.from_tuples(arrays, names=('Upper', 'Lower'))
pd.DataFrame({'Score':['perfect','good','fair','bad']},index=mul_index)

(b)通过from_product

L1 = ['A','B']
L2 = ['a','b']
pd.MultiIndex.from_product([L1,L2],names=('Upper', 'Lower'))
#两两相乘

(c)指定df中的列创建(set_index方法)

df_using_mul = df.set_index(['Class','Address'])
df_using_mul.head()

2.多层索引切片

df_using_mul.head()

(a)一般切片
df_using_mul.loc['C_2','street_5']当索引不排序时,单个索引会报出性能警告,df_using_mul.index.is_lexsorted()——is_lexsorted()函数检查是否排序

print(df_using_mul.sort_index().loc['C_2','street_5'])
#df_using_mul.sort_index().index.is_lexsorted()
               School Gender  Height  Weight  Math Physics
Class Address                                             
C_2   street_5    S_1      M     188      68  97.0      A-
      street_5    S_1      F     162      63  33.8       B
      street_5    S_2      M     193     100  39.1       B
#df_using_mul.loc[('C_2','street_5'):] 报错
#当不排序时,不能使用多层切片
df_using_mul.sort_index().loc[('C_2','street_6'):('C_3','street_4')]
#注意此处由于使用了loc,因此仍然包含右端点
              School Gender  Height  Weight  Math Physics
Class Address                                             
C_2   street_6    S_1      M     160      53  58.8      A+
      street_6    S_1      F     167      63  68.4      B-
      street_7    S_2      F     194      77  68.5      B+
      street_7    S_2      F     183      76  85.4       B
C_3   street_1    S_1      F     175      57  87.7      A-
      street_2    S_1      M     195      70  85.2       A
      street_4    S_1      M     161      68  31.5      B+
      street_4    S_2      F     157      78  72.3      B+
      street_4    S_2      M     187      73  48.9       B
print(df_using_mul.sort_index().loc[('C_2','street_7'):'C_3'].head())
#非元组也是合法的,表示选中该层所有元素
               School Gender  Height  Weight  Math Physics
Class Address                                             
C_2   street_7    S_2      F     194      77  68.5      B+
      street_7    S_2      F     183      76  85.4       B
C_3   street_1    S_1      F     175      57  87.7      A-
      street_2    S_1      M     195      70  85.2       A
      street_4    S_1      M     161      68  31.5      B+

(b)第一类特殊情况:由元组构成列表
表示选出在‘C_2’且第二层在’street_7’和’C_3’中第二层在’street_2’中的行

df_using_mul.sort_index().loc[[('C_2','street_7'),('C_3','street_2')]]

(c)第二类特殊情况:由列表构成元组
选出第一层在‘C_2’和’C_3’中且第二层在’street_2’和’street_7’中的行

df_using_mul.sort_index().loc[(['C_2','C_3'],['street_2','street_7']),:]

上面(b)(c)两种是不一样的。在pandas的索引方面,元组和列表的处理方式并不相同。元组被解释为一个多级密钥,而列表用于指定多个密钥。或者换句话说,元组水平移动(遍历级别),列表垂直移动(扫描级别)​​。

print("df_using_mul.sort_index().loc[[('C_2','street_7'),('C_3','street_2')]]")
print(df_using_mul.sort_index().loc[[('C_2','street_7'),('C_3','street_2')]])
print("df_using_mul.sort_index().loc[(['C_2','C_3'],['street_2','street_7']),:]")
print(df_using_mul.sort_index().loc[(['C_2','C_3'],['street_2','street_7']),:])
df_using_mul.sort_index().loc[[('C_2','street_7'),('C_3','street_2')]]
               School Gender  Height  Weight  Math Physics
Class Address                                             
C_2   street_7    S_2      F     194      77  68.5      B+
      street_7    S_2      F     183      76  85.4       B
C_3   street_2    S_1      M     195      70  85.2       A
df_using_mul.sort_index().loc[(['C_2','C_3'],['street_2','street_7']),:]
               School Gender  Height  Weight  Math Physics
Class Address                                             
C_2   street_7    S_2      F     194      77  68.5      B+
      street_7    S_2      F     183      76  85.4       B
C_3   street_2    S_1      M     195      70  85.2       A
      street_7    S_1      M     188      82  49.7       B
      street_7    S_2      F     190      99  65.9       C

3.多层索引中的slice对象

pandas.IndexSlice索引Slice的使用非常灵活

L1,L2 = ['A','B','C'],['a','b','c']
mul_index1 = pd.MultiIndex.from_product([L1,L2],names=('Upper', 'Lower'))
L3,L4 = ['D','E','F'],['d','e','f']
mul_index2 = pd.MultiIndex.from_product([L3,L4],names=('Big', 'Small'))
df_s = pd.DataFrame(np.random.rand(9,9),index=mul_index1,columns=mul_index2)
print(df_s)
idx=pd.IndexSlice
print(df_s.loc[idx['B':,df_s['D']['d']>0.1],idx[df_s.sum()>5]])
#df_s.sum()默认为对列求和,因此返回一个长度为9的数值列表
df_s.sum()>4
Big                 D                             E                      \
Small               d         e         f         d         e         f   
Upper Lower                                                               
A     a      0.459655  0.059706  0.121672  0.217739  0.909185  0.169267   
      b      0.360565  0.144908  0.342706  0.888209  0.755053  0.332857   
      c      0.893656  0.875571  0.594975  0.152043  0.586393  0.534965   
B     a      0.413867  0.898946  0.428148  0.261815  0.895837  0.476977   
      b      0.089534  0.042910  0.004747  0.520944  0.685936  0.606698   
      c      0.851241  0.113117  0.816423  0.742133  0.851448  0.851022   
C     a      0.137159  0.111936  0.935954  0.119665  0.552744  0.273147   
      b      0.422194  0.345720  0.083829  0.689388  0.173288  0.664126   
      c      0.431836  0.358073  0.332712  0.988001  0.132478  0.544948   

Big                 F                      
Small               d         e         f  
Upper Lower                                
A     a      0.088769  0.278117  0.602913  
      b      0.766804  0.658145  0.670062  
      c      0.328405  0.642212  0.178812  
B     a      0.812680  0.284388  0.367059  
      b      0.565505  0.276578  0.489664  
      c      0.495446  0.881650  0.562261  
C     a      0.983574  0.091926  0.426801  
      b      0.971695  0.844064  0.177657  
      c      0.785137  0.863913  0.340610  
Big                 E         F
Small               e         d
Upper Lower                    
B     a      0.895837  0.812680
      c      0.851448  0.495446
C     a      0.552744  0.983574
      b      0.173288  0.971695
      c      0.132478  0.785137
      
Big  Small
D    d         True
     e        False
     f        False
E    d         True
     e         True
     f         True
F    d         True
     e         True
     f        False
dtype: bool

idx['B':,df_s['D']['d']>0.1]是对行索引的约束('B':是第一层,df_s['D']['d']>0.1是第二层),idx[df_s.sum()>5]是对列索引的约束。

4.索引层的交换

(a)swaplevel方法(两层交换)

print(df_using_mul.head())
print(df_using_mul.swaplevel(i=1,j=0,axis=0).sort_index().head())
#sortlevel则根据各级别中的值对数据进行排序,通常用swaplevel是也会用到sortlevel
#df1.swaplevel('key1','key2')表示将这2个索引互换位置; df1.sortlevel(1)和df1.sort_index(level=1)表示按key2的值升序排列
print(df_using_mul.swaplevel('Address','Class').sort_index().head())
               School Gender  Height  Weight  Math Physics
Class Address                                             
C_1   street_1    S_1      M     173      63  34.0      A+
      street_2    S_1      F     192      73  32.5      B+
      street_2    S_1      M     186      82  87.2      B+
      street_2    S_1      F     167      81  80.4      B-
      street_4    S_1      F     159      64  84.8      B+
               School Gender  Height  Weight  Math Physics
Address  Class                                            
street_1 C_1      S_1      M     173      63  34.0      A+
         C_2      S_2      M     175      74  47.2      B-
         C_3      S_1      F     175      57  87.7      A-
street_2 C_1      S_1      F     192      73  32.5      B+
         C_1      S_1      M     186      82  87.2      B+
               School Gender  Height  Weight  Math Physics
Address  Class                                            
street_1 C_1      S_1      M     173      63  34.0      A+
         C_2      S_2      M     175      74  47.2      B-
         C_3      S_1      F     175      57  87.7      A-
street_2 C_1      S_1      F     192      73  32.5      B+
         C_1      S_1      M     186      82  87.2      B+

(b)reorder_levels方法(多层交换)

df_muls = df.set_index(['School','Class','Address'])
print(df_muls)
print(df_muls.reorder_levels([2,0,1],axis=0).sort_index().head())
#如果索引有name,可以直接使用name
#print(df_muls.reorder_levels(['Address','School','Class'],axis=0).sort_index().head())
                      Gender  Height  Weight  Math Physics
School Class Address                                      
S_1    C_1   street_1      M     173      63  34.0      A+
             street_2      F     192      73  32.5      B+
             street_2      M     186      82  87.2      B+
             street_2      F     167      81  80.4      B-
             street_4      F     159      64  84.8      B+
       C_2   street_5      M     188      68  97.0      A-
             street_4      F     176      94  63.5      B-
             street_6      M     160      53  58.8      A+
             street_5      F     162      63  33.8       B
             street_6      F     167      63  68.4      B-
       C_3   street_4      M     161      68  31.5      B+
             street_1      F     175      57  87.7      A-
             street_7      M     188      82  49.7       B
             street_2      M     195      70  85.2       A
             street_5      F     187      69  61.7      B-
S_2    C_1   street_7      M     174      84  83.3       C
             street_6      F     161      61  50.6      B+
             street_4      M     157      61  52.5      B-
             street_5      F     159      97  72.2      B+
             street_4      M     170      81  34.2       A
       C_2   street_5      M     193     100  39.1       B
             street_7      F     194      77  68.5      B+
             street_4      M     155      91  73.8      A+
             street_1      M     175      74  47.2      B-
             street_7      F     183      76  85.4       B
       C_3   street_4      F     157      78  72.3      B+
             street_5      M     171      88  32.7       A
             street_7      F     190      99  65.9       C
             street_6      F     164      81  95.5      A-
             street_4      M     187      73  48.9       B
       C_4   street_2      F     192      62  45.3       A
             street_7      M     166      82  48.7       B
             street_6      F     158      60  59.7      B+
             street_2      F     160      84  67.7       B
             street_6      F     193      54  47.6       B
                      Gender  Height  Weight  Math Physics
Address  School Class                                     
street_1 S_1    C_1        M     173      63  34.0      A+
                C_3        F     175      57  87.7      A-
         S_2    C_2        M     175      74  47.2      B-
street_2 S_1    C_1        F     192      73  32.5      B+
                C_1        M     186      82  87.2      B+

三、索引设定

1.index_col参数

index_col是read_csv中的一个参数,而不是某一个方法。设置读入时的索引。

pd.read_csv('work/table.csv',index_col=['Address','School']).head()

2.reindex和reindex_like

reindex是指重新索引,它的重要特性在于索引对齐,很多时候用于重新排序。

print(df.head())
print('指定四行')
print(df.reindex(index=[1101,1203,1206,2402]))
print('指定三列')
print(df.reindex(columns=['Height','Gender','Average']).head())
print('可以选择缺失值的填充方法:fill_value和method(bfill/ffill/nearest),其中method参数必须索引单调')
print(df.reindex(index=[1101,1203,1206,2402],method='bfill'))
print('bfill表示用所在索引1206的后一个有效行填充,ffill为前一个有效行,nearest是指最近的')
print(df.reindex(index=[1101,1203,1206,2402],method='nearest'))
print("数值上1205比1301更接近1206,因此用前者填充")
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1103    S_1   C_1      M  street_2     186      82  87.2      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+
指定四行
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1   173.0    63.0  34.0      A+
1203    S_1   C_2      M  street_6   160.0    53.0  58.8      A+
1206    NaN   NaN    NaN       NaN     NaN     NaN   NaN     NaN
2402    S_2   C_4      M  street_7   166.0    82.0  48.7       B
指定三列
      Height Gender  Average
ID                          
1101     173      M      NaN
1102     192      F      NaN
1103     186      M      NaN
1104     167      F      NaN
1105     159      F      NaN
可以选择缺失值的填充方法:fill_value和method(bfill/ffill/nearest),其中method参数必须索引单调
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1203    S_1   C_2      M  street_6     160      53  58.8      A+
1206    S_1   C_3      M  street_4     161      68  31.5      B+
2402    S_2   C_4      M  street_7     166      82  48.7       B
bfill表示用所在索引1206的后一个有效行填充,ffill为前一个有效行,nearest是指最近的
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1203    S_1   C_2      M  street_6     160      53  58.8      A+
1206    S_1   C_2      F  street_6     167      63  68.4      B-
2402    S_2   C_4      M  street_7     166      82  48.7       B
数值上1205比1301更接近1206,因此用前者填充

reindex_like的作用为生成一个横纵索引完全与参数列表一致的DataFrame,数据使用被调用的表。

df_temp = pd.DataFrame({'Weight':np.zeros(5),
                        'Height':np.zeros(5),
                        'ID':[1101,1104,1103,1106,1102]}).set_index('ID')
print(pd.DataFrame({'Weight':np.zeros(5),
                        'Height':np.zeros(5),
                        'ID':[1101,1104,1103,1106,1102]}))
print(df_temp)
print(df_temp.reindex_like(df[0:5][['Weight','Height']]))
print(df[0:5][['Weight','Height']].reindex_like(df_temp))
   Weight  Height    ID
0     0.0     0.0  1101
1     0.0     0.0  1104
2     0.0     0.0  1103
3     0.0     0.0  1106
4     0.0     0.0  1102
      Weight  Height
ID                  
1101     0.0     0.0
1104     0.0     0.0
1103     0.0     0.0
1106     0.0     0.0
1102     0.0     0.0
      Weight  Height
ID                  
1101     0.0     0.0
1102     0.0     0.0
1103     0.0     0.0
1104     0.0     0.0
1105     NaN     NaN
      Weight  Height
ID                  
1101    63.0   173.0
1104    81.0   167.0
1103    82.0   186.0
1106     NaN     NaN
1102    73.0   192.0

df_temp索引单调还可以使用method参数。

:
df_temp = pd.DataFrame({'Weight':range(5),
                        'Height':range(5),
                        'ID':[1101,1104,1103,1106,1102]}).set_index('ID').sort_index()
df_temp.reindex_like(df[0:5][['Weight','Height']],method='bfill')
#可以自行检验这里的1105的值是否是由bfill规则填充
	Weight	Height
ID		
1101	0	0
1102	4	4
1103	2	2
1104	1	1
1105	3	3

3.set_index和reset_index

set_index:从字面意思看,就是将某些列作为索引。
reset_index:主要功能是将索引重置,默认状态直接恢复到自然数索引。

reset_index()
函数原型:DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill=’’)
参数解释:
level:int、str、tuple或list,默认无,仅从索引中删除给定级别。默认情况下移除所有级别。控制了具体要还原的那个等级的索引
drop:drop为False则索引列会被还原为普通列,否则会丢失
inplace:默认为false,适当修改DataFrame(不要创建新对象)
col_level:int或str,默认值为0,如果列有多个级别,则确定将标签插入到哪个级别。默认情况下,它将插入到第一级。
col_fill:对象,默认‘’,如果列有多个级别,则确定其他级别的命名方式。如果没有,则重复索引名
————————————————
版权声明:本文为CSDN博主「_KJ」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cuit2016123070/java/article/details/83624074

print(df.head())
print('set_index 使用表内列')
print(df.set_index('Class').head())
print('set_index利用append参数可以将当前索引维持不变')
print(df.set_index('Class',append=True).head())
print('set_index 当使用与表长相同的列作为索引(需要先转化为Series,否则报错)')
print(df.set_index(pd.Series(range(df.shape[0]))).head())
print('set_index可以直接添加多级索引')
print(df.set_index([pd.Series(range(df.shape[0])),pd.Series(np.ones(df.shape[0]))]).head())
print('reset_index()默认状态直接恢复到自然数索引')
print(df.reset_index().head())
print('reset_index()用level参数指定哪一层被reset,用col_level参数指定set到哪一层')
L1,L2 = ['A','B','C'],['a','b','c']
mul_index1 = pd.MultiIndex.from_product([L1,L2],names=('Upper', 'Lower'))
L3,L4 = ['D','E','F'],['d','e','f']
mul_index2 = pd.MultiIndex.from_product([L3,L4],names=('Big', 'Small'))
df_temp = pd.DataFrame(np.random.rand(9,9),index=mul_index1,columns=mul_index2)
print(df_temp.head())
df_temp1 = df_temp.reset_index(level=1,col_level=1)
df_temp2 = df_temp.reset_index(level=0,col_level=0)
print('对level=i处理,即对默认从左到右的自然数i(从0开始)处理')
print(df_temp1.head())
print(df_temp2.head())
print("看到的确插入了('Upper',  ''),( '', 'Lower')")
print(df_temp.columns)
print(df_temp2.columns)
print(df_temp1.columns)
print('最内层索引被移出')
print(df_temp1.index)
print(df_temp2.index)
print(df_temp.index)
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1103    S_1   C_1      M  street_2     186      82  87.2      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+
set_index 使用表内列
      School Gender   Address  Height  Weight  Math Physics
Class                                                      
C_1      S_1      M  street_1     173      63  34.0      A+
C_1      S_1      F  street_2     192      73  32.5      B+
C_1      S_1      M  street_2     186      82  87.2      B+
C_1      S_1      F  street_2     167      81  80.4      B-
C_1      S_1      F  street_4     159      64  84.8      B+
set_index利用append参数可以将当前索引维持不变
           School Gender   Address  Height  Weight  Math Physics
ID   Class                                                      
1101 C_1      S_1      M  street_1     173      63  34.0      A+
1102 C_1      S_1      F  street_2     192      73  32.5      B+
1103 C_1      S_1      M  street_2     186      82  87.2      B+
1104 C_1      S_1      F  street_2     167      81  80.4      B-
1105 C_1      S_1      F  street_4     159      64  84.8      B+
set_index 当使用与表长相同的列作为索引(需要先转化为Series,否则报错)
  School Class Gender   Address  Height  Weight  Math Physics
0    S_1   C_1      M  street_1     173      63  34.0      A+
1    S_1   C_1      F  street_2     192      73  32.5      B+
2    S_1   C_1      M  street_2     186      82  87.2      B+
3    S_1   C_1      F  street_2     167      81  80.4      B-
4    S_1   C_1      F  street_4     159      64  84.8      B+
set_index可以直接添加多级索引
      School Class Gender   Address  Height  Weight  Math Physics
0 1.0    S_1   C_1      M  street_1     173      63  34.0      A+
1 1.0    S_1   C_1      F  street_2     192      73  32.5      B+
2 1.0    S_1   C_1      M  street_2     186      82  87.2      B+
3 1.0    S_1   C_1      F  street_2     167      81  80.4      B-
4 1.0    S_1   C_1      F  street_4     159      64  84.8      B+
reset_index()默认状态直接恢复到自然数索引
     ID School Class Gender   Address  Height  Weight  Math Physics
0  1101    S_1   C_1      M  street_1     173      63  34.0      A+
1  1102    S_1   C_1      F  street_2     192      73  32.5      B+
2  1103    S_1   C_1      M  street_2     186      82  87.2      B+
3  1104    S_1   C_1      F  street_2     167      81  80.4      B-
4  1105    S_1   C_1      F  street_4     159      64  84.8      B+
reset_index()用level参数指定哪一层被reset,用col_level参数指定set到哪一层
Big                 D                             E                      \
Small               d         e         f         d         e         f   
Upper Lower                                                               
A     a      0.628774  0.617775  0.034992  0.624555  0.099748  0.548236   
      b      0.032905  0.039415  0.569866  0.618430  0.721538  0.354901   
      c      0.543318  0.206034  0.010119  0.609791  0.780001  0.194281   
B     a      0.243125  0.827316  0.790221  0.729359  0.925731  0.183670   
      b      0.616933  0.363978  0.099167  0.676308  0.241399  0.682956   

Big                 F                      
Small               d         e         f  
Upper Lower                                
A     a      0.109781  0.304292  0.558305  
      b      0.578825  0.458627  0.485772  
      c      0.373286  0.328466  0.858915  
B     a      0.615336  0.930666  0.106575  
      b      0.713162  0.830740  0.246136  
对level=i处理,即对默认从左到右的自然数i(从0开始)处理
Big                 D                             E                      \
Small Lower         d         e         f         d         e         f   
Upper                                                                     
A         a  0.628774  0.617775  0.034992  0.624555  0.099748  0.548236   
A         b  0.032905  0.039415  0.569866  0.618430  0.721538  0.354901   
A         c  0.543318  0.206034  0.010119  0.609791  0.780001  0.194281   
B         a  0.243125  0.827316  0.790221  0.729359  0.925731  0.183670   
B         b  0.616933  0.363978  0.099167  0.676308  0.241399  0.682956   

Big           F                      
Small         d         e         f  
Upper                                
A      0.109781  0.304292  0.558305  
A      0.578825  0.458627  0.485772  
A      0.373286  0.328466  0.858915  
B      0.615336  0.930666  0.106575  
B      0.713162  0.830740  0.246136  
Big   Upper         D                             E                      \
Small               d         e         f         d         e         f   
Lower                                                                     
a         A  0.628774  0.617775  0.034992  0.624555  0.099748  0.548236   
b         A  0.032905  0.039415  0.569866  0.618430  0.721538  0.354901   
c         A  0.543318  0.206034  0.010119  0.609791  0.780001  0.194281   
a         B  0.243125  0.827316  0.790221  0.729359  0.925731  0.183670   
b         B  0.616933  0.363978  0.099167  0.676308  0.241399  0.682956   

Big           F                      
Small         d         e         f  
Lower                                
a      0.109781  0.304292  0.558305  
b      0.578825  0.458627  0.485772  
c      0.373286  0.328466  0.858915  
a      0.615336  0.930666  0.106575  
b      0.713162  0.830740  0.246136  
看到的确插入了('Upper',  ''),( '', 'Lower')
MultiIndex([('D', 'd'),
            ('D', 'e'),
            ('D', 'f'),
            ('E', 'd'),
            ('E', 'e'),
            ('E', 'f'),
            ('F', 'd'),
            ('F', 'e'),
            ('F', 'f')],
           names=['Big', 'Small'])
MultiIndex([('Upper',  ''),
            (    'D', 'd'),
            (    'D', 'e'),
            (    'D', 'f'),
            (    'E', 'd'),
            (    'E', 'e'),
            (    'E', 'f'),
            (    'F', 'd'),
            (    'F', 'e'),
            (    'F', 'f')],
           names=['Big', 'Small'])
MultiIndex([( '', 'Lower'),
            ('D',     'd'),
            ('D',     'e'),
            ('D',     'f'),
            ('E',     'd'),
            ('E',     'e'),
            ('E',     'f'),
            ('F',     'd'),
            ('F',     'e'),
            ('F',     'f')],
           names=['Big', 'Small'])
最内层索引被移出
Index(['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'], dtype='object', name='Upper')
Index(['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'], dtype='object', name='Lower')
MultiIndex([('A', 'a'),
            ('A', 'b'),
            ('A', 'c'),
            ('B', 'a'),
            ('B', 'b'),
            ('B', 'c'),
            ('C', 'a'),
            ('C', 'b'),
            ('C', 'c')],
           names=['Upper', 'Lower'])

4.rename_axis和rename

rename_axis是针对多级索引的方法,作用是修改某一层的索引名,而不是索引标签。
rename方法用于修改列或者行索引标签,而不是索引名。

print(df_temp.rename_axis(index={'Lower':'LowerLower'},columns={'Big':'BigBig'}))
print(df_temp.rename(index={'A':'T'},columns={'e':'changed_e'}).head())
BigBig                   D                             E                      \
Small                    d         e         f         d         e         f   
Upper LowerLower                                                               
A     a           0.628774  0.617775  0.034992  0.624555  0.099748  0.548236   
      b           0.032905  0.039415  0.569866  0.618430  0.721538  0.354901   
      c           0.543318  0.206034  0.010119  0.609791  0.780001  0.194281   
B     a           0.243125  0.827316  0.790221  0.729359  0.925731  0.183670   
      b           0.616933  0.363978  0.099167  0.676308  0.241399  0.682956   
      c           0.707237  0.609917  0.857135  0.609399  0.972564  0.810882   
C     a           0.516834  0.162424  0.686295  0.715906  0.724892  0.274689   
      b           0.044545  0.403304  0.189982  0.049760  0.593413  0.255300   
      c           0.000849  0.101672  0.514457  0.024007  0.994960  0.599054   

BigBig                   F                      
Small                    d         e         f  
Upper LowerLower                                
A     a           0.109781  0.304292  0.558305  
      b           0.578825  0.458627  0.485772  
      c           0.373286  0.328466  0.858915  
B     a           0.615336  0.930666  0.106575  
      b           0.713162  0.830740  0.246136  
      c           0.228018  0.015488  0.836605  
C     a           0.403612  0.728454  0.447956  
      b           0.578274  0.697135  0.253684  
      c           0.104305  0.727621  0.422090  
Big                 D                             E                      \
Small               d changed_e         f         d changed_e         f   
Upper Lower                                                               
T     a      0.628774  0.617775  0.034992  0.624555  0.099748  0.548236   
      b      0.032905  0.039415  0.569866  0.618430  0.721538  0.354901   
      c      0.543318  0.206034  0.010119  0.609791  0.780001  0.194281   
B     a      0.243125  0.827316  0.790221  0.729359  0.925731  0.183670   
      b      0.616933  0.363978  0.099167  0.676308  0.241399  0.682956   

Big                 F                      
Small               d changed_e         f  
Upper Lower                                
T     a      0.109781  0.304292  0.558305  
      b      0.578825  0.458627  0.485772  
      c      0.373286  0.328466  0.858915  
B     a      0.615336  0.930666  0.106575  
      b      0.713162  0.830740  0.246136  

四、常用索引型函数

1.where函数

print(df.head())
print("当对条件为False的单元进行填充,不满足条件的行全部默认被设置为NaN")
print(df.where(df['Gender']=='M').head())
print("通过这种方法筛选结果和[]操作符的结果完全一致")
print(df.where(df['Gender']=='M').dropna().head())
print("第一个参数为布尔条件,第二个参数为填充值")
print(df.where(df['Gender']=='M',np.random.rand(df.shape[0],df.shape[1])).head())
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1103    S_1   C_1      M  street_2     186      82  87.2      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+
当对条件为False的单元进行填充,不满足条件的行全部默认被设置为NaN
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1   173.0    63.0  34.0      A+
1102    NaN   NaN    NaN       NaN     NaN     NaN   NaN     NaN
1103    S_1   C_1      M  street_2   186.0    82.0  87.2      B+
1104    NaN   NaN    NaN       NaN     NaN     NaN   NaN     NaN
1105    NaN   NaN    NaN       NaN     NaN     NaN   NaN     NaN
通过这种方法筛选结果和[]操作符的结果完全一致
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1   173.0    63.0  34.0      A+
1103    S_1   C_1      M  street_2   186.0    82.0  87.2      B+
1201    S_1   C_2      M  street_5   188.0    68.0  97.0      A-
1203    S_1   C_2      M  street_6   160.0    53.0  58.8      A+
1301    S_1   C_3      M  street_4   161.0    68.0  31.5      B+
第一个参数为布尔条件,第二个参数为填充值
        School      Class    Gender   Address      Height     Weight  \
ID                                                                     
1101       S_1        C_1         M  street_1  173.000000  63.000000   
1102  0.508756   0.347268  0.435964  0.992553    0.991152   0.692039   
1103       S_1        C_1         M  street_2  186.000000  82.000000   
1104  0.573049   0.162712  0.281136  0.632705    0.216306   0.587828   
1105  0.632075  0.0574599  0.775192  0.324902    0.697140   0.758236   

           Math   Physics  
ID                         
1101  34.000000        A+  
1102   0.627440  0.879285  
1103  87.200000        B+  
1104   0.284405  0.917676  
1105   0.451666  0.208062  

2.mask函数

mask函数与where功能上相反,其余完全一致,即对条件为True的单元进行填充。

3.query函数

基于DataFrame列的计算代数式,对于按照某列的规则进行过滤的操作。query函数中的布尔表达式中,下面的符号都是合法的:行列索引名、字符串、and/not/or/&/|/~/not in/in/==/!=、四则运算符。

df.query('(Address in ["street_6","street_7"])&(Weight>(70+10))&(ID in [1303,2304,2402])')

五、重复元素处理

1.duplicated方法

该方法返回了是否重复的布尔列表。

print(df.duplicated('Class').head())
print("可选参数keep默认为first,即首次出现设为不重复,若为last,则最后一次设为不重复,若为False,则所有重复项为False")
#print(df.duplicated('Class',keep=False).head())
#df.duplicated('Class',keep='last').tail()

可选参数keep默认为first,即首次出现设为不重复,若为last,则最后一次设为不重复,若为False,则所有重复项为False

ID
1101    False
1102     True
1103     True
1104     True
1105     True
dtype: bool

2.drop_duplicates方法

剔除重复项,这在后面章节中的分组操作中可能是有用的,例如需要保留每组的第一个值。参数与duplicate函数类似。在传入多列时等价于将多列共同视作一个多级索引,比较重复项。

print(df.drop_duplicates('Class'))
print("在传入多列时等价于将多列共同视作一个多级索引,比较重复项")
print(df.drop_duplicates(['School','Class']))
 School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1201    S_1   C_2      M  street_5     188      68  97.0      A-
1301    S_1   C_3      M  street_4     161      68  31.5      B+
2401    S_2   C_4      F  street_2     192      62  45.3       A
在传入多列时等价于将多列共同视作一个多级索引,比较重复项
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1201    S_1   C_2      M  street_5     188      68  97.0      A-
1301    S_1   C_3      M  street_4     161      68  31.5      B+
2101    S_2   C_1      M  street_7     174      84  83.3       C
2201    S_2   C_2      M  street_5     193     100  39.1       B
2301    S_2   C_3      F  street_4     157      78  72.3      B+
2401    S_2   C_4      F  street_2     192      62  45.3       A

六、抽样函数

这里的抽样函数指的就是sample函数。
n为样本量;frac为抽样比;replace为是否放回;
axis为抽样维度,默认为0,即抽行;
weights为样本权重,自动归一化;

print(df.sample(frac=0.1,replace=True))
print('放回情形下,有可能有重复取出同一个ID动作')
print(df.sample(n=35,replace=True).index.is_unique)
print(df.sample(n=3,axis=1).head())
print(df.sample(n=3,weights=np.random.rand(df.shape[0])).head())
print("以某一列为权重,这在抽样理论中很常见")
print(df.sample(n=3,weights=df['Math']).head())
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
2304    S_2   C_3      F  street_6     164      81  95.5      A-
1103    S_1   C_1      M  street_2     186      82  87.2      B+
2205    S_2   C_2      F  street_7     183      76  85.4       B
2204    S_2   C_2      M  street_1     175      74  47.2      B-
放回情形下,有可能有重复取出同一个ID动作
False
     School Class  Math
ID                     
1101    S_1   C_1  34.0
1102    S_1   C_1  32.5
1103    S_1   C_1  87.2
1104    S_1   C_1  80.4
1105    S_1   C_1  84.8
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
2401    S_2   C_4      F  street_2     192      62  45.3       A
2103    S_2   C_1      M  street_4     157      61  52.5      B-
1305    S_1   C_3      F  street_5     187      69  61.7      B-
以某一列为权重,这在抽样理论中很常见
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
2403    S_2   C_4      F  street_6     158      60  59.7      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
2304    S_2   C_3      F  street_6     164      81  95.5      A-

七、问题与练习(附解答)

1. 问题

【问题一】 如何更改列或行的顺序?如何交换奇偶行(列)的顺序?

位置用iloc,可以在切片设置[0::2][1::2]。

【问题二】 如果要选出DataFrame的某个子集,请给出尽可能多的方法实现。

如开头总结的,行用loc,列用[ ],位置用iloc。

【问题三】 query函数比其他索引方法的速度更慢吗?在什么场合使用什么索引最高效?

query函数是基于DataFrame列的计算代数式,对于按照某列的规则进行过滤的操作。其功能还是挺强大的,在数据集不大的时候主要是看个人习惯吧。

【问题四】 单级索引能使用Slice对象吗?能的话怎么使用,请给出一个例子。

貌似是可以的。
df = pd.read_csv('work/table.csv',index_col='ID')
df.loc[idx['1103':],:]

【问题五】 如何快速找出某一列的缺失值所在索引?

#先构建一个有缺失值的数据表
data=pd.DataFrame({'name':['Kite','Lily','Hanmei','Danny','Bob'],'English':[92,78,np.nan,23,82],'Math':[69,87,91,np.nan,90],'Chinese':[np.nan,78,96,np.nan,75]})
print(data)
#缺失值为"NaN"
data.query('(Chinese in ["NaN"])').index
#可见结果是0,3
     name  English  Math  Chinese
0    Kite     92.0  69.0      NaN
1    Lily     78.0  87.0     78.0
2  Hanmei      NaN  91.0     96.0
3   Danny     23.0   NaN      NaN
4     Bob     82.0  90.0     75.0
Int64Index([0, 3], dtype='int64')

【问题六】 索引设定中的所有方法分别适用于哪些场合?怎么直接把某个DataFrame的索引换成任意给定同长度的索引?

回答下第二问
df = pd.read_csv('work/table.csv',index_col='ID')
df.set_index(pd.Series(np.random.rand(df.shape[0]))).head()

【问题七】 多级索引有什么适用场合?

有多层限制条件下对比条件的影响。

【问题八】 什么时候需要重复元素处理?

比如上一篇pandas基础最后练习的第二题。

2. 练习

【练习一】 现有一份关于UFO的数据集UFO.csv,请解决下列问题:
(a)在所有被观测时间超过60s的时间中,哪个形状最多?
(b)对经纬度进行划分:-180°至180°以30°为一个划分,-90°至90°以18°为一个划分,请问哪个区域中报告的UFO事件数量最多?

ex1 = pd.read_csv('work/UFO.csv')
ex1.head()
print('(a)在所有被观测时间超过60s的时间中,哪个形状最多?')
print(ex1[ex1['duration (seconds)']>60]['shape'].value_counts().index[0])
print('(b)对经纬度进行划分:-180°至180°以30°为一个划分,-90°至90°以18°为一个划分,请问哪个区域中报告的UFO事件数量最多?')
ex1['longitude_interval'] = pd.cut(ex1['longitude'],bins=pd.interval_range(start=-180,end=180,freq=30))
ex1['latitude_interval'] = pd.cut(ex1['latitude'],bins=pd.interval_range(start=-90,end=90,freq=18))
print(ex1.set_index(['longitude_interval','latitude_interval']).index.value_counts().index[0])
(a)在所有被观测时间超过60s的时间中,哪个形状最多?
light
(b)对经纬度进行划分:-180°至180°以30°为一个划分,-90°至90°以18°为一个划分,请问哪个区域中报告的UFO事件数量最多?
(Interval(-90, -60, closed='right'), Interval(36, 54, closed='right'))

【练习二】 现有一份关于口袋妖怪的数据集Pokemon.csv,请解决下列问题:
(a)双属性的Pokemon占总体比例的多少?
(b)在所有种族值(Total)不小于580的Pokemon中,非神兽(Legendary=False)的比例为多少?
(c)在第一属性为格斗系(Fighting)的Pokemon中,物攻排名前三高的是哪些?
(d)请问六项种族指标(HP、物攻、特攻、物防、特防、速度)极差的均值最大的是哪个属性(只考虑第一属性,且均值是对属性而言)?
(e)哪个属性(只考虑第一属性)的神兽比例最高?该属性神兽的种族值也是最高的吗?

ex2 = pd.read_csv('work/Pokemon.csv')
ex2.head()
print("(a)双属性的Pokemon占总体比例的多少?")
print(ex2['Type 2'].count()/ex2.shape[0])
print('(b)在所有种族值(Total)不小于580的Pokemon中,非神兽(Legendary=False)的比例为多少?')
print(1-ex2[ex2['Total']>=580]['Legendary'].sum()/ex2[ex2['Total']>=580].shape[0])
print("(c)在第一属性为格斗系(Fighting)的Pokemon中,物攻排名前三高的是哪些?")
print(ex2.loc[ex2[ex2['Type 1']=='Fighting']['Attack'].sort_values().tail(3).index]['Name'])
#print(ex2.loc[ex2[ex2['Type 1']=='Fighting']['Attack'].sort_values().tail(3).index])
print("(d)请问六项种族指标(HP、物攻、特攻、物防、特防、速度)极差的均值最大的是哪个属性(只考虑第一属性,且均值是对属性而言)?")
dict={}
ex2['极差'] = ex2.iloc[:,5:11].max(axis=1)-ex2.iloc[:,5:11].min(axis=1)
for i in list(ex2.drop_duplicates('Type 1')['Type 1']):
    dict[i]=ex2[ex2['Type 1']==i]['极差'].mean()
max_value = max(dict.values())
#不能避免有多个相同最大值,所以要遍历
max_list = []
for m, n in dict.items():       
	if n == max_value:
		max_list.append(m)
print(" ".join(max_list)+'属性(只考虑第一属性)六项种族指标(HP、物攻、特攻、物防、特防、速度)极差的均值最大')
print("(e)哪个属性(只考虑第一属性)的神兽比例最高?该属性神兽的种族值也是最高的吗?")
dict={}
ex3=ex2[ex2['Legendary']==1]
for i in list(ex2.drop_duplicates('Type 1')['Type 1']):
    dict[i]=ex3[ex2['Type 1']==i].shape[0]/ex2[ex2['Type 1']==i].shape[0]
max_value = max(dict.values())
#不能避免有多个相同最大值,所以要遍历
max_list = []
for m, n in dict.items():       
	if n == max_value:
		max_list.append(m)
print(" ".join(max_list)+'属性(只考虑第一属性)的神兽比例最高')
import warnings
warnings.filterwarnings("ignore")
dict={}
ex3=ex2[ex2['Legendary']==1]
for i in list(ex2.drop_duplicates('Type 1')['Type 1']):
    dict[i]=ex3[ex2['Type 1']==i]['Total'].mean()
max_value = max(dict.values())
#不能避免有多个相同最大值,所以要遍历
max_list = []
for m, n in dict.items():       
	if n == max_value:
		max_list.append(m)
print(" ".join(max_list)+'属性神兽的种族值最高')
#其实(d)和(e)的两次可以合并一道计算
(a)双属性的Pokemon占总体比例的多少?
0.5175
(b)在所有种族值(Total)不小于580的Pokemon中,非神兽(Legendary=False)的比例为多少?
0.4247787610619469
(c)在第一属性为格斗系(Fighting)的Pokemon中,物攻排名前三高的是哪些?
74                 Machamp
594             Conkeldurr
498    LucarioMega Lucario
Name: Name, dtype: object
(d)请问六项种族指标(HP、物攻、特攻、物防、特防、速度)极差的均值最大的是哪个属性(只考虑第一属性,且均值是对属性而言)?
Steel属性(只考虑第一属性)六项种族指标(HP、物攻、特攻、物防、特防、速度)极差的均值最大
(e)哪个属性(只考虑第一属性)的神兽比例最高?该属性神兽的种族值也是最高的吗?
Flying属性(只考虑第一属性)的神兽比例最高
Normal属性神兽的种族值最高

Reference

  1. pandas官网
  2. Joyful-Pandas
  3. python 常用的几个镜像仓库

你可能感兴趣的:(Pandas教程)