pandas学习笔记(三)

pandas学习笔记(三)

索引器

1.表的索引

通过[ ]来实现。通过[列名]可以从DataFrame中取出相应的列,返回值为Series

df = pd.read_csv('./pokemon.csv')
df['name'].head()

Out[5]: 
0     Bulbasaur
1       Ivysaur
2      Venusaur
3    Charmander
4    Charmeleon
Name: name, dtype: object

如果要取出多个列,则可以通过[列名组成的列表],其返回值为一个DataFrame

df[['name','attack']].head()

Out[6]: 
         name  attack
0   Bulbasaur      49
1     Ivysaur      62
2    Venusaur     100
3  Charmander      52
4  Charmeleon      64

此外,若要取出单列,且列名中不包含空格,则可以用.列名取出,这和[列名]是等价的:

df.name.head()

Out[7]: 
0     Bulbasaur
1       Ivysaur
2      Venusaur
3    Charmander
4    Charmeleon
Name: name, dtype: object
2.序列的行索引
以字符串为索引:

取出单个索引的对应元素,用[item];取出多个用[items的列表];取出某两个索引之间的元素,且这两个索引是在整个索引中唯一出现,则可以使用切片。

Series只有单个值对应,则返回这个标量值,如果有多个值对应,则返回一个Series

s = pd.Series([1,2,3,4,5,6],index=['a', 'b', 'a', 'a', 'a', 'c'])

s['a']
Out[9]: 
a    1
a    3
a    4
a    5
dtype: int64
s['b']
Out[10]: 2

s[['c','b']]
Out[12]: 
c    6
b    2
dtype: int64

s['c':'b':-2]
Out[15]: 
c    6
a    4
b    2
dtype: int64
以整数为索引:

在使用数据的读入函数时,如果不特别指定所对应的列作为索引,那么会生成从0开始的整数索引作为默认索引。当然,任意一组符合长度要求的整数都可以作为索引。

和字符串一样,如果使用[int][int_list],则可以取出对应索引元素的值:

s = pd.Series(['a', 'b', 'c', 'd', 'e', 'f'], index=[1, 3, 1, 2, 5, 4])

s[1]
Out[17]: 
1    a
1    c
dtype: object

s[[2,3]]
Out[18]: 
2    d
3    b
dtype: object

warning:不要把纯浮点以及任何混合类型(字符串、整数、浮点类型等的混合)作为索引,否则可能会在具体的操作时报错或者返回非预期的结果

3.loc索引器

loc索引器:

形式:一般形式是 loc[*, *],其中第一个*代表行的选择,第二个 *代表列的选择,如果省略第二个位置写作loc[*],这个*是指行的筛选。

参数对象:
1.单个元素 2.元素列表 3.元素切片 4.布尔列表 5.函数

*为单个元素:

直接取出相应的行或列,如果元素在索引中重复则结果为DataFrame,否则为Series

# 只选择行
print(df_demo.loc['Qiang Sun']) # 多个人叫此名字
print(df_demo.loc['Quan Zhao']) # 名字唯一
                                  School      Grade  Gender  Weight Transfer
Name                                                                        
Qiang Sun            Tsinghua University     Junior  Female    53.0        N
Qiang Sun            Tsinghua University  Sophomore  Female    40.0        N
Qiang Sun  Shanghai Jiao Tong University     Junior  Female     NaN        N

School      Shanghai Jiao Tong University
Grade                              Junior
Gender                             Female
Weight                                 53
Transfer                                N
Name: Quan Zhao, dtype: object

# 同时选择行和列
print(df_demo.loc['Qiang Sun', 'School') # 返回Series
print(df_demo.loc['Quan Zhao', 'School']) # 返回单个元素
Name
Qiang Sun              Tsinghua University
Qiang Sun              Tsinghua University
Qiang Sun    Shanghai Jiao Tong University
Name: School, dtype: object

'Shanghai Jiao Tong University'
*为元素列表:

取出列表中所有元素值对应的行或列

df_demo.loc[['Qiang Sun','Quan Zhao'], ['School','Gender']]

                                  School  Gender
Name                                            
Qiang Sun            Tsinghua University  Female
Qiang Sun            Tsinghua University  Female
Qiang Sun  Shanghai Jiao Tong University  Female
Quan Zhao  Shanghai Jiao Tong University  Female

*为元素切片

之前的Series使用字符串索引时提到,如果是唯一值的起点和终点字符,那么就可以使用切片,并且包含两个端点,如果不唯一则报错

df_demo.loc['Gaojuan You':'Gaoqiang Qian', 'School':'Gender']
                                      School      Grade  Gender
Name                                                           
Gaojuan You                 Fudan University  Sophomore    Male
Xiaoli Qian              Tsinghua University   Freshman  Female
Qiang Chu      Shanghai Jiao Tong University   Freshman  Female
Gaoqiang Qian            Tsinghua University     Junior  Female

                          School   Grade  Gender  Weight Transfer
5               Fudan University  Junior  Female    46.0        N
4            Tsinghua University  Senior  Female    50.0        N
3  Shanghai Jiao Tong University  Senior  Female    45.0        N
*为布尔列表

在实际的数据处理中,根据条件来筛选行是极其常见的,此处传入loc的布尔列表与DataFrame长度相同,且列表为True的位置所对应的行会被选中,False则会被剔除。

例如,选出体重超过70kg的学生:

df_demo.loc[df_demo.Weight>70].head()
                                      School      Grade Gender  Weight Transfer
Name                                                                           
Mei Sun        Shanghai Jiao Tong University     Senior   Male    89.0        N
Gaojuan You                 Fudan University  Sophomore   Male    74.0        N
Xiaopeng Zhou  Shanghai Jiao Tong University   Freshman   Male    74.0        N
Xiaofeng Sun             Tsinghua University     Senior   Male    71.0        N
Qiang Zheng    Shanghai Jiao Tong University     Senior   Male    87.0        N

#注意:对于复合条件,可以用 |(或), &(且),~(取反) 的组合来实现
*为函数

这里的函数,必须以前面的四种合法形式之一为返回值,并且函数的输入值为DataFrame本身。假设仍然是上述复合条件筛选的例子,可以把逻辑写入一个函数中再返回,需要注意的是函数的形式参数x本质上即为df_demo

def condition(x):
    condition_1_1 = x.School == 'Fudan University'
    condition_1_2 = x.Grade == 'Senior'
    condition_1_3 = x.Weight > 70
    condition_1 = condition_1_1 & condition_1_2 & condition_1_3
    condition_2_1 = x.School == 'Peking University'
    condition_2_2 = x.Grade == 'Senior'
    condition_2_3 = x.Weight > 80
    condition_2 = condition_2_1 & (~condition_2_2) & condition_2_3
    result = condition_1 | condition_2
    return result
  
df_demo.loc[condition_1 | condition_2]
	                           School     Grade Gender  Weight Transfer
Name                                                               
Qiang Han       Peking University  Freshman   Male    87.0        N
Chengpeng Zhou   Fudan University    Senior   Male    81.0        N
Changpeng Zhao  Peking University  Freshman   Male    83.0        N
Chengpeng Qian   Fudan University    Senior   Male    73.0        Y

此外,还支持使用lambda表达式,其返回值也同样必须是先前提到的四种形式之一

df_demo.loc[lambda x:'Quan Zhao', lambda x:'Gender']
Out[6]:'Female'

函数无法返回如start: end: step的切片形式,故返回切片时要用 slice对象进行包装

df_demo.loc[lambda x: slice('Gaojuan You', 'Gaoqiang Qian')]
# 结果和*参数为切片的结果一样
4.iloc索引器

iloc的使用与loc完全类似,只不过是针对位置进行筛选,在相应的*位置处一共也有五类合法对象,分别是:整数、整数列表、整数切片、布尔列表以及函数,函数的返回值必须是前面的四类合法对象中的一个,其输入同样也为DataFrame本身。

# 整数
df_demo.iloc[1, 1] # 第二行第二列
# 'Freshman'

# 整数列表
df_demo.iloc[[0, 1], [0, 1]] # 前两行前两列
'''
                                       School     Grade
Name                                                   
Gaopeng Yang    Shanghai Jiao Tong University  Freshman
Changqiang You              Peking University  Freshman
'''
# 整数切片
df_demo.iloc[1: 4, 2:4] # 切片不包含结束端点
'''
                Gender  Weight
Name                          
Changqiang You    Male    70.0
Mei Sun           Male    89.0
Xiaojuan Sun    Female    41.0
'''
# 函数
df_demo.iloc[lambda x: slice(1, 4)] # 传入切片为返回值的函数
'''
                                       School      Grade  Gender  Weight Transfer
Name                                                                             
Changqiang You              Peking University   Freshman    Male    70.0        N
Mei Sun         Shanghai Jiao Tong University     Senior    Male    89.0        N
Xiaojuan Sun                 Fudan University  Sophomore  Female    41.0        N
'''

在使用布尔列表的时候要特别注意,不能传入Series而必须传入序列的values,否则会报错。因此,在使用布尔筛选的时候还是应当优先考虑loc的方式。

df_demo.iloc[(df_demo.Weight>80).values].head()

                                       School      Grade Gender  Weight Transfer
Name                                                                            
Mei Sun         Shanghai Jiao Tong University     Senior   Male    89.0        N
Qiang Zheng     Shanghai Jiao Tong University     Senior   Male    87.0        N
Qiang Han                   Peking University   Freshman   Male    87.0        N
Chengpeng Zhou               Fudan University     Senior   Male    81.0        N
Feng Han        Shanghai Jiao Tong University  Sophomore   Male    82.0        N

5.query方法

pandas中,支持把字符串形式的查询表达式传入query方法来查询数据,其表达式的执行结果必须返回布尔列表。在进行复杂索引时,由于这种检索方式无需像普通方法一样重复使用DataFrame的名字来引用列名,一般而言会使代码长度在不降低可读性的前提下有所减少。

loc一节中的复合条件查询例子可以如下改写:

df.query('((School == "Fudan University")&'
         ' (Grade == "Senior")&'
         ' (Weight > 70))|'
         '((School == "Peking University")&'
         ' (Grade != "Senior")&'
         ' (Weight > 80))')

School Grade Name Gender Weight Transfer
38 Peking University Freshman Qiang Han Male 87.0 N
66 Fudan University Senior Chengpeng Zhou Male 81.0 N
99 Peking University Freshman Changpeng Zhao Male 83.0 N
131 Fudan University Senior Chengpeng Qian Male 73.0 Y
6.随机抽样

sample函数中的主要参数为n, axis, frac, replace, weights,前三个分别是指抽样数量、抽样的方向(0为行、1为列)和抽样比例(0.3则为从总体中抽出30%的样本)。

replaceweights分别是指是否放回和每个样本的抽样相对概率,当replace = True则表示有放回抽样。

例如,对下面构造的df_samplevalue值的相对大小为抽样概率进行有放回抽样,抽样数量为3。

df_sample = pd.DataFrame({'id': list('abcde'),
			'value': [1, 2, 3, 4, 90]})
print(df_sample)
id value
0 a 1
1 b 2
2 c 3
3 d 4
4 e 90
df_sample.sample(3, replace = True, weights = df_sample.value)
id value
4 e 90
3 d 4
4 e 90

多级索引

1.多级索引及其表的结构

下图通过颜色区分,标记了DataFrame的结构。与单层索引的表一样,具备元素值、行索引和列索引三个部分。其中,这里的行索引和列索引都是MultiIndex类型,只不过索引中的一个元素是元组而不是单层索引中的标量。例如,行索引的第四个元素为("B", "Male"),列索引的第二个元素为("Height", "Senior")

这里需要注意,外层连续出现相同的值时,第一次之后出现的会被隐藏显示,使结果的可读性增强。

在这里插入图片描述

与单层索引类似,MultiIndex也具有名字属性,图中的SchoolGender分别对应了表的第一层和第二层行索引的名字,IndicatorGrade分别对应了第一层和第二层列索引的名字。

索引的名字和值属性分别可以通过namesvalues获得:

df_multi.index.names
# FrozenList(['School', 'Gender'])
df_multi.columns.names
#  FrozenList(['Indicator', 'Grade'])
df_multi.index.values
'''
array([('A', 'Female'), ('A', 'Male'), ('B', 'Female'), ('B', 'Male'),
  	   ('C', 'Female'), ('C', 'Male'), ('D', 'Female'), ('D', 'Male')],
       dtype=object)
'''
df_multi.columns.values
'''
array([('Height', 'Freshman'), ('Height', 'Senior'),
  	   ('Height', 'Sophomore'), ('Height', 'Junior'),
  	   ('Weight', 'Freshman'), ('Weight', 'Senior'),
  	   ('Weight', 'Sophomore'), ('Weight', 'Junior')], dtype=object)
'''

如果想要得到某一层的索引,则需要通过get_level_values获得:

df_multi.index.get_level_values(0)

Index(['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D'], dtype='object', name='School')

但对于索引而言,无论是单层还是多层,用户都无法通过index_obj[0] = item的方式来修改元素,也不能通过index_name[0] = new_name的方式来修改名字

2. 多级索引中loc索引器

例:将学校和年级设为索引

df_multi = df.set_index(['School', 'Grade'])
df_multi.head()
'''
                                                   Name  Gender  Weight Transfer
School                        Grade                                             
Shanghai Jiao Tong University Freshman     Gaopeng Yang  Female    46.0        N
Peking University             Freshman   Changqiang You    Male    70.0        N
Shanghai Jiao Tong University Senior            Mei Sun    Male    89.0        N
Fudan University              Sophomore    Xiaojuan Sun  Female    41.0        N
                          	  Sophomore     Gaojuan You    Male    74.0        N
'''

由于多级索引中的单个元素以元组为单位,因此之前在第一节介绍的lociloc方法完全可以照搬,只需把标量的位置替换成对应的元组,不过在索引前最好对MultiIndex进行排序以避免性能警告

df_multi = df_multi.sort_index()
df_multi.loc[('Fudan University', 'Junior')].head()
'''
                              Name  Gender  Weight Transfer
School           Grade                                         
Fudan University Junior  Yanli You  Female    48.0        N
             Junior  Chunqiang Chu    Male    72.0        N
             Junior   Changfeng Lv    Male    76.0        N
             Junior     Yanjuan Lv  Female    49.0      NaN
             Junior  Gaoqiang Zhou  Female    43.0        N
'''
df_multi.loc[df_multi.Weight > 70].head() # 布尔列表也是可用的
'''
                               Name Gender  Weight Transfer
School           Grade                                           
Fudan University Freshman       Feng Wang   Male    74.0        N
             	 Junior     Chunqiang Chu   Male    72.0        N
             	 Junior      Changfeng Lv   Male    76.0        N
             	 Senior    Chengpeng Zhou   Male    81.0        N
            	 Senior    Chengpeng Qian   Male    73.0        Y
'''

特殊用法:在多级索引中的元组有一种特殊的用法,可以对多层的元素进行交叉组合后索引,但同时需要指定 loc的列,全选则用: 表示。其中,每一层需要选中的元素用列表存放,传入 loc的形式为[(level_0_list, level_1_list), cols]

例:得到所有北大和复旦的大二大三学生

res = df_multi.loc[(['Peking University', 'Fudan University'],
	              ['Sophomore', 'Junior']), :]
res.head()
'''
                                     Name  Gender  Weight Transfer
School            Grade                                           
Peking University Sophomore   Changmei Xu  Female    43.0        N
              	  Sophomore  Xiaopeng Qin    Male     NaN        N
              	  Sophomore        Mei Xu  Female    39.0        N
              	  Sophomore   Xiaoli Zhou  Female    55.0        N
              	  Sophomore      Peng Han  Female    34.0      NaN

'''
res.shape
# (33, 4)
3.lndexSlice对象

前面介绍的方法,即使在索引不重复的时候,也只能对元组整体进行切片,而不能对每层进行切片,也不允许将切片和布尔列表混合使用,引入IndexSlice对象就能解决这个问题。Slice对象一共有两种形式,第一种为loc[idx[*,*]]型,第二种为loc[idx[*,*],idx[*,*]]型,下面将进行介绍。为了方便演示,下面构造一个索引不重复的DataFrame

loc[idx[*,*]]

型:这种情况并不能进行多层分别切片,前一个 *表示行的选择,后一个 *表示列的选择,与单纯的loc 是类似的

df_ex.loc[idx['C':, ('D', 'f'):]]
'''
Big          D  E        F      
Small        f  d  e  f  d  e  f
Upper Lower                     
C     a      2  5  9 -9  5 -6  3
  	  b     -5 -3 -5  6 -6  3 -5
  	  c      6 -6  6  4  7  8 -4
'''
# 也支持布尔序列的索引
df_ex.loc[idx[:'A', lambda x:x.sum()>0]] # 列和大于0
'''
Big          D     F
Small        d  e  e
Upper Lower         
A     a      3  6  9
  	  b     -3  3 -4
  	  c     -1  0  9
'''
loc[idx[*,*],idx[*,*]]

这种情况能够分层进行切片,前一个idx指代的是行索引,后一个是列索引。

df_ex.loc[idx[:'A', 'b':], idx['E':, 'e':]]
'''
Big          E     F   
Small        e  f  e  f
Upper Lower            
A     b     -2  5 -4  4
  	  c      6  6  9 -6

'''	
多级索引的构造

前面提到了多级索引表的结构和切片,那么除了使用set_index之外,如何自己构造多级索引呢?常用的有from_tuples, from_arrays, from_product三种方法,它们都是pd.MultiIndex对象下的函数。

from_tuples指根据传入由元组组成的列表进行构造:

my_tuple = [('a','cat'),('a','dog'),('b','cat'),('b','dog')]
pd.MultiIndex.from_tuples(my_tuple, names=['First','Second'])
'''
MultiIndex([('a', 'cat'),
            ('a', 'dog'),
        	('b', 'cat'),
        	('b', 'dog')],
      	 names=['First', 'Second'])	
'''

from_arrays指根据传入列表中,对应层的列表进行构造:

my_array = [list('aabb'), ['cat', 'dog']*2]
pd.MultiIndex.from_arrays(my_array, names=['First','Second'])
'''
MultiIndex([('a', 'cat'),
        	('a', 'dog'),
        	('b', 'cat'),
        	('b', 'dog')],
       		names=['First', 'Second'])
'''

from_product指根据给定多个列表的笛卡尔积进行构造:

my_list1 = ['a','b']
my_list2 = ['cat','dog']
pd.MultiIndex.from_product([my_list1,
                          	my_list2],
                         	names=['First','Second'])
'''
MultiIndex([('a', 'cat'),
        	('a', 'dog'),
        	('b', 'cat'),
        	('b', 'dog')],
       	names=['First', 'Second'])

'''

索引的常用方法

1.索引层的交换和删除

构造的三级索引 :在这里插入图片描述

索引层的交换:由 swaplevelreorder_levels 完成,前者只能交换两个层,而后者可以交换任意层,两者都可以指定交换的是轴是哪一个,即行索引或列索引。

df_ex.swaplevel(0,2,axis=1).head() # 列索引的第一层和第三层交换
'''
Other             cat dog cat dog cat dog cat dog
Small               c   c   d   d   c   c   d   d
Big                 C   C   C   C   D   D   D   D
Upper Lower Extra                                
A     a     alpha   3   6  -9  -6  -6  -2   0   9
        	beta   -5  -3   3  -8  -3  -2   5   8
  	  b     alpha  -4   4  -1   0   7  -4   6   6
        	beta   -9   9  -6   8   5  -2  -9  -8
B     a     alpha   0  -9   1  -6   2   9  -7  -9
'''
df_ex.reorder_levels([2,0,1],axis=0).head() # 列表数字指代原来索引中的层
'''
Big                 C               D            
Small               c       d       c       d    
Other             cat dog cat dog cat dog cat dog
Extra Upper Lower                                
alpha A     a       3   6  -9  -6  -6  -2   0   9
beta  A     a      -5  -3   3  -8  -3  -2   5   8
alpha A     b      -4   4  -1   0   7  -4   6   6
beta  A     b      -9   9  -6   8   5  -2  -9  -8
alpha B     a       0  -9   1  -6   2   9  -7  -9
'''

删除某一层的索引:使用droplevel方法

df_ex.droplevel(1,axis=1)
'''
Big                 C               D            
Other             cat dog cat dog cat dog cat dog
Upper Lower Extra                                
A     a     alpha   3   6  -9  -6  -6  -2   0   9
        	beta   -5  -3   3  -8  -3  -2   5   8
  	  b     alpha  -4   4  -1   0   7  -4   6   6
        	beta   -9   9  -6   8   5  -2  -9  -8
B     a     alpha   0  -9   1  -6   2   9  -7  -9
        	beta   -9  -5  -4  -3  -1   8   6  -5
 	  b     alpha   0   1  -8  -8  -2   0  -6  -3
        	beta    2   5   9  -9   5  -6   3   1
'''
2.索引属性的修改

通过rename_axis可以对索引层的名字进行修改,常用的修改方式是传入字典的映射:

 df_ex.rename_axis(index={'Upper':'Changed_row'},
                   columns={'Other':'Changed_Col'}).head()
 '''
Big                       C               D            
Small                     c       d       c       d    
Changed_Col             cat dog cat dog cat dog cat dog
Changed_row Lower Extra                                
A           a     alpha   3   6  -9  -6  -6  -2   0   9
              	  beta   -5  -3   3  -8  -3  -2   5   8
            b     alpha  -4   4  -1   0   7  -4   6   6
              	  beta   -9   9  -6   8   5  -2  -9  -8
B           a     alpha   0  -9   1  -6   2   9  -7  -9
 '''             

通过rename可以对索引的值进行修改,如果是多级索引需要指定修改的层号level

df_ex.rename(columns={'cat':'not_cat'},
             level=2).head()
'''
Big                     C                       D                
Small                   c           d           c           d    
Other             not_cat dog not_cat dog not_cat dog not_cat dog
Upper Lower Extra                                                
A     a     alpha       3   6      -9  -6      -6  -2       0   9
        	beta       -5  -3       3  -8      -3  -2       5   8
      b     alpha      -4   4      -1   0       7  -4       6   6
        	beta       -9   9      -6   8       5  -2      -9  -8
B     a     alpha       0  -9       1  -6       2   9      -7  -9
'''          

传入参数也可以是函数,其输入值就是索引元素:

df_ex.rename(index=lambda x:str.upper(x),
            level=2).head()
'''
Big                 C               D            
Small               c       d       c       d    
Other             cat dog cat dog cat dog cat dog
Upper Lower Extra                                
A     a     ALPHA   3   6  -9  -6  -6  -2   0   9
        	BETA   -5  -3   3  -8  -3  -2   5   8
  	  b     ALPHA  -4   4  -1   0   7  -4   6   6
        	BETA   -9   9  -6   8   5  -2  -9  -8
B     a     ALPHA   0  -9   1  -6   2   9  -7  -9
'''           
posted @ 2020-12-22 22:38  AiGgBoY  阅读(132)  评论(0编辑  收藏  举报