前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据分析索引总结(下)Pandas索引技巧

数据分析索引总结(下)Pandas索引技巧

作者头像
Datawhale
发布2020-06-04 11:57:22
2.8K0
发布2020-06-04 11:57:22
举报
文章被收录于专栏:Datawhale专栏

作者:闫钟峰,Datawhale优秀学习者

寄语:本文对索引设定、常用索引型函数、重复元素处理、抽样函数等内容做了详细介绍。

索引设定

1. index_col参数

index_col是read_csv中的一个参数,而不是某一个方法,在使用 read_csv 函数读取文本的时候使用index_col参数指定用哪几个列作为索引
代码语言:javascript
复制
pd.read_csv('data/table.csv',index_col=['Address','School']).head()

2. reindex和reindex_like

reindex是指重新索引,它的重要特性在于索引对齐,很多时候用于重新排序。
代码语言:javascript
复制
df.head()
通过为reindex参数指定一个新的list,使得原始df的行重新排列。
代码语言:javascript
复制
df.reindex(index=sorted(list(df.index),reverse=True)).head()
如果传入的list是原始index的一个真子集, 则会实现分层抽样的效果
代码语言:javascript
复制
df.reindex(index=list(df.index)[::5])
为index传入的参数可以不是df的原始index中的值---这将引入缺失值构成的行,还可以传入重复索引。
代码语言:javascript
复制
df.reindex(index=[1101,1101,1203,1206,2402])
为columns传入参数,将对列索引做类似的事情。
代码语言:javascript
复制
df.reindex(columns=['Height','Height','Gender','Average']).head()
同时为index和columns传入原始index和columns 的真子集, 同样可以实现获取原始df的子df的目的。由于reindex的copy参数默认值是True,这时会返回一个新的变量,而不是修改原始df。
代码语言:javascript
复制
df.reindex(index=[1101,1203,2402],columns=['Height','Gender'])
可以选择缺失值的填充方法:
fill_value和method(bfill/ffill/nearest),其中method参数必须索引单调。bfill表示用所在索引1206的后一个有效行填充,ffill为前一个有效行。
代码语言:javascript
复制
df.reindex(index=[1101,1203,1206,2402],method='bfill')
数值上1205比1301更接近1206,因此用前者填充。nearest的最近, 是指在原始df中离得最近的,这个离得最近的可能并没有在被 reindex 的时候选中。
代码语言:javascript
复制
df.reindex(index=[1101,1203,1206,2402,1205,1301],method='nearest')
reindex_like的作用为生成一个横纵索引完全与参数列表一致的DataFrame,数据使用被调用的表。
代码语言:javascript
复制
df_temp = pd.DataFrame({'Weight':np.zeros(5),
                        'Height':np.zeros(5),
                        'ID':[1101,1104,1103,1106,1102]}).set_index('ID')
表中的值数据来自于df_temp, 而行索引和列索引则来自于传入的 df[0:5][['Weight','Height']]。由于df_temp中没有1105这个行索引,因此会引入缺失值。
代码语言:javascript
复制
df_temp.reindex_like(df[0:5][['Weight','Height']])
使用reindex方法实现上述reindex_like的效果--reindex_like可以看作是该方法的语法糖。
代码语言:javascript
复制
df_temp.reindex(index=df[0:5][['Weight','Height']].index,columns=df[0:5][['Weight','Height']].columns)
如果df_temp单调还可以使用method参数。
代码语言:javascript
复制
df_temp = pd.DataFrame({'Weight':range(5),
                        'Height':range(5),
                        'ID':[1101,1104,1103,1106,1102]}).set_index('ID').sort_index()
可以自行检验这里的1105的值是否是由bfill规则填充
代码语言:javascript
复制
df_temp.reindex_like(df[0:5][['Weight','Height']],method='bfill')
注意是用1105这个索引在df.temp中的前边或后边的值进行填充,
代码语言:javascript
复制
df_temp.reindex_like(df[0:5][['Weight','Height']],method='ffill')
使用reindex实现相同的效果。
代码语言:javascript
复制
df_temp.reindex(index=df[0:5][['Weight','Height']].index,columns=df[0:5][['Weight','Height']].columns,method='ffill')

3. set_index和reset_index

先介绍set_index:从字面意思看,就是将某些列作为索引。使用表内列作为索引:
代码语言:javascript
复制
df.head()
将df的列设置为索引, 参数 drop 默认丢弃原来的索引。
代码语言:javascript
复制
df.set_index('Class').head()
利用append参数可以将当前索引维持不变
这种情况下会把新的索引作为次级索引。
代码语言:javascript
复制
df.set_index('Class',append=True).head()
使用与表长相同的列作为索引(需要先转化为Series,否则报错)
代码语言:javascript
复制
df.set_index(pd.Series(range(df.shape[0]))).head()
如果恰好列名是用的默认整数索引, 并且包含了传入的参数,是否这些列会被设置成索引?
代码语言:javascript
复制
df_=pd.DataFrame(np.random.randn(24).reshape((3,8)))
df_.set_index(list(range(df_.shape[0])))
# 传入参数是 range(df_.shape[0] 时会报错:
# KeyError: 'None of [range(0, 3)] are in the columns'
# 当给 set_index 传入的是list的时候, 就会把列名和list一致的列设置为索引
看参数说明,并不一定需要Series
代码语言:javascript
复制
df.set_index(np.arange(df.shape[0])).head()
可以直接添加多级索引:
传入由多个类似 Series 的元素构成的list, 就会用这个多个类Series的元素作为多级索引。
代码语言:javascript
复制
df.set_index([pd.Series(range(df.shape[0])),pd.Series(np.ones(df.shape[0]))]).head()
下面介绍reset_index方法,它的主要功能是将索引重置为df的列
默认状态直接恢复到自然数索引:
代码语言:javascript
复制
df.reset_index().head()
多级索引时用level参数指定哪一层被reset,用col_level参数指定将索引名称set到多重列索引的哪一层:
代码语言:javascript
复制
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)
将编号为1的行索引(也就是次级索引)重置为列, 原来的次级索引名作为列索引的编号为0(也就是列索引的顶级索引),这时该列的次级列索引为空。
代码语言:javascript
复制
df_temp1 = df_temp.reset_index(level=1,col_level=0)
移出最内层索引
代码语言:javascript
复制
df_temp1.index

4. rename_axis和rename

rename_axis是针对多级索引的方法,作用是修改某一层索引的索引名(index.name),而不是索引的索引值(索引标签)
这里为index和columns传入的均是一个字典,键为原来的索引名称,值为新的索引名称。
代码语言:javascript
复制
df_temp.rename_axis(index={'Lower':'LowerLower'},columns={'Big':'BigBig'})
还可以直接使用赋值语句修改或命名索引--当原始索引并没有名字的时候,这种方式更加便捷。
代码语言:javascript
复制
df_temp.index.names=['UPPER','LOWER']
代码语言:javascript
复制
dftemp=pd.DataFrame(np.random.randn(20).reshape(10,2), index=pd.MultiIndex.from_tuples(list(np.random.randint(1,5,30).reshape(-1,3)))).sort_index()
由于索引的name为空,因此使用rename_index无法将其重命名。
代码语言:javascript
复制
dftemp.rename_axis(index={0:'LEFT',2:'RIGHT'},)
但是用赋值语句可以修改各层级索引的名字---能否只修改某一层级的索引的名字?
代码语言:javascript
复制
dftemp.index.names=['LEFT','MIDDLE','RIGHT']
重置dftemp
代码语言:javascript
复制
dftemp=pd.DataFrame(np.random.randn(20).reshape(10,2), index=pd.MultiIndex.from_tuples(list(np.random.randint(1,5,30).reshape(-1,3)))).sort_index()
但是用赋值语句可以修改各层级索引的名字---可以只修改某一层级的索引的名字?
代码语言:javascript
复制
# 传入一个和索引层级等长的list, 不需要命名的层级赋值 None, 需要命名的层级传入字符串
dftemp.index.names=[None,None,'RIGHT']
当然非层次化索引也可以用rename_axis重命名索引名。
代码语言:javascript
复制
df_temp1.rename_axis(index={'Upper':'UPPER'})
rename方法用于修改列或者行索引标签,而不是索引名

给index传入的字典,键是原来的索引值, 值是新的索引值。无需指定要修改的索引级别,会自动寻找索引中的相应的值----当不同层级的索引有相同的值的时候,这会造成混乱。

代码语言:javascript
复制
df_temp.rename(index={'A':'T'},columns={'e':'changed_e'}).head()
当不同层级的索引有相同的值的时候,这会造成混乱。
代码语言:javascript
复制
L1,L2 = ['A','B','C'],['a','b','c']
mul_index1 = pd.MultiIndex.from_product([L1,L1],names=('Upper1', 'Upper2'))
L3,L4 = ['D','E','F'],['d','e','f']
mul_index2 = pd.MultiIndex.from_product([L3,L4],names=('Big', 'Small'))
df_t = pd.DataFrame(np.random.rand(9,9),index=mul_index1,columns=mul_index2)
当不同层级的索引有相同的值的时候,这会造成混乱--注意行索引的每一层的 A 都被改为了 T。
代码语言:javascript
复制
df_t.rename(index={'A':'T'},columns={'e':'changed_e'}).head()
代码语言:javascript
复制
# 如果要同时修改行索引的第二层,以及列索引的第一层,怎么指定level?
代码语言:javascript
复制
df_t.rename(index={'A':'T'},level=1,columns={'E':'changed_e'},level=0).head()
# 显然不能同时指定两个level
一个问题:如果不同层级的索引的索引值有相同的值的时候,要想修改特定级别的索引的索引值(比如次级索引中的A,修改为a),需要如何修改?
答:使用参数level=1指定需要修改的层级为次级索引
代码语言:javascript
复制
df_t.rename(index={'A':'T'},columns={'e':'changed_e'},level=1).head()

常用索引型函数

1. where函数

当对条件为False的单元进行填充,不满足条件的行全部被设置为NaN
代码语言:javascript
复制
df.where(df['Gender']=='M').head()
注意和query的区别
代码语言:javascript
复制
df.query('Gender=="M"').head()
where函数需要增加一个dropna()才会和query等价,通过这种方法筛选结果和[ ]操作符的结果完全一致。
代码语言:javascript
复制
df.where(df['Gender']=='M').dropna().head()
[] 操作符--实际上是传入了布尔值索引。
代码语言:javascript
复制
df[df['Gender']=='M'].head()
第一个参数con为布尔条件,第二个参数other为填充值
代码语言:javascript
复制
df.where(df['Gender']=='M',np.random.rand(df.shape[0],df.shape[1])).head()

2. mask函数

mask函数与where功能上相反,其余完全一致,即对条件为True的单元进行填充
代码语言:javascript
复制
df.mask(df['Gender']!='M').dropna().head()
df.mask(df['Gender']!='M',np.random.rand(df.shape[0],df.shape[1])).head()

3. query函数

query函数中的布尔表达式中,下面的符号都是合法的:行列索引名、字符串、and / not / or / & / | / ~ / not in / in /==/!=、四则运算符。
代码语言:javascript
复制
df.query('(Address in ["street_6","street_7"])&(Weight>(70+10))&(ID in [1303,2304,2402])')
实际上就是根据列值满足的条件筛选行---基本上和sql里的where子句对应。注意传入的参数是带引号的

重复元素处理

1. duplicated方法

该方法返回了是否重复的布尔列表。
代码语言:javascript
复制
df.duplicated('Class').head()
可选参数keep默认为first,即首次出现设为不重复,若为last,则最后一次设为不重复,若为False,则所有重复项为False。
代码语言:javascript
复制
df.duplicated('Class',keep='last').tail()
df.duplicated('Class',keep=False).head() # - False : Mark all duplicates as ``True``.

2. drop_duplicates方法

从名字上看出为剔除重复项,这在后面章节中的分组操作中可能是有用的,例如需要保留每组的第一个值:
代码语言:javascript
复制
df.drop_duplicates('Class')
上边有些类似于mysql中按某列groupby之后,还能选择其他的非分组列。
代码语言:javascript
复制
df.drop_duplicates('Class',keep='last')
在传入多列时等价于将多列共同视作一个多级索引,比较重复项:
代码语言:javascript
复制
df.drop_duplicates(['School','Class'])

抽样函数

这里的抽样函数指的就是sample函数

1. n为样本量

代码语言:javascript
复制
df.sample(n=5)
df.sample(9)#由于是第一个参数,可以省略 n=

2. frac为抽样比

代码语言:javascript
复制
df.sample(frac=0.05)

3. replace为是否放回

代码语言:javascript
复制
df.sample(n=df.shape[0],replace=True).head()
# 有放回(replace=True)可以选择比df长度更多的元素回来
len(df.sample(n=123,replace=True)),len(df)
df.sample(n=35,replace=True).index.is_unique

4. axis为抽样维度,默认为0,即抽行

代码语言:javascript
复制
# axis=1 对列进行抽样
df.sample(n=3,axis=1).head()

5. weights为样本权重,自动归一化

代码语言:javascript
复制
w=np.random.rand(df.shape[0])
df.sample(n=3,weights=w).head()

以某一列为权重,这在抽样理论中很常见

代码语言:javascript
复制
df.sample(n=3,weights=df['Math']).head()

以某一列为权重,这在抽样理论中很常见--本质上是以这一列的列值为权重

代码语言:javascript
复制
df.sample(n=3,weights=df['Math'].values).head()
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Datawhale 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 索引设定
  • 1. index_col参数
    • index_col是read_csv中的一个参数,而不是某一个方法,在使用 read_csv 函数读取文本的时候使用index_col参数指定用哪几个列作为索引
      • 2. reindex和reindex_like
        • reindex是指重新索引,它的重要特性在于索引对齐,很多时候用于重新排序。
        • 通过为reindex参数指定一个新的list,使得原始df的行重新排列。
        • 如果传入的list是原始index的一个真子集, 则会实现分层抽样的效果
        • 为index传入的参数可以不是df的原始index中的值---这将引入缺失值构成的行,还可以传入重复索引。
        • 为columns传入参数,将对列索引做类似的事情。
        • 同时为index和columns传入原始index和columns 的真子集, 同样可以实现获取原始df的子df的目的。由于reindex的copy参数默认值是True,这时会返回一个新的变量,而不是修改原始df。
        • 可以选择缺失值的填充方法:
        • fill_value和method(bfill/ffill/nearest),其中method参数必须索引单调。bfill表示用所在索引1206的后一个有效行填充,ffill为前一个有效行。
        • 数值上1205比1301更接近1206,因此用前者填充。nearest的最近, 是指在原始df中离得最近的,这个离得最近的可能并没有在被 reindex 的时候选中。
        • reindex_like的作用为生成一个横纵索引完全与参数列表一致的DataFrame,数据使用被调用的表。
        • 表中的值数据来自于df_temp, 而行索引和列索引则来自于传入的 df[0:5][['Weight','Height']]。由于df_temp中没有1105这个行索引,因此会引入缺失值。
        • 使用reindex方法实现上述reindex_like的效果--reindex_like可以看作是该方法的语法糖。
        • 如果df_temp单调还可以使用method参数。
        • 可以自行检验这里的1105的值是否是由bfill规则填充
        • 注意是用1105这个索引在df.temp中的前边或后边的值进行填充,
        • 使用reindex实现相同的效果。
      • 3. set_index和reset_index
        • 先介绍set_index:从字面意思看,就是将某些列作为索引。使用表内列作为索引:
        • 将df的列设置为索引, 参数 drop 默认丢弃原来的索引。
        • 利用append参数可以将当前索引维持不变
        • 这种情况下会把新的索引作为次级索引。
        • 使用与表长相同的列作为索引(需要先转化为Series,否则报错)
        • 如果恰好列名是用的默认整数索引, 并且包含了传入的参数,是否这些列会被设置成索引?
        • 看参数说明,并不一定需要Series
        • 可以直接添加多级索引:
        • 传入由多个类似 Series 的元素构成的list, 就会用这个多个类Series的元素作为多级索引。
        • 下面介绍reset_index方法,它的主要功能是将索引重置为df的列
        • 默认状态直接恢复到自然数索引:
        • 多级索引时用level参数指定哪一层被reset,用col_level参数指定将索引名称set到多重列索引的哪一层:
        • 将编号为1的行索引(也就是次级索引)重置为列, 原来的次级索引名作为列索引的编号为0(也就是列索引的顶级索引),这时该列的次级列索引为空。
        • 移出最内层索引
      • 4. rename_axis和rename
        • rename_axis是针对多级索引的方法,作用是修改某一层索引的索引名(index.name),而不是索引的索引值(索引标签)
        • 这里为index和columns传入的均是一个字典,键为原来的索引名称,值为新的索引名称。
        • 还可以直接使用赋值语句修改或命名索引--当原始索引并没有名字的时候,这种方式更加便捷。
        • 由于索引的name为空,因此使用rename_index无法将其重命名。
        • 但是用赋值语句可以修改各层级索引的名字---能否只修改某一层级的索引的名字?
        • 重置dftemp
        • 但是用赋值语句可以修改各层级索引的名字---可以只修改某一层级的索引的名字?
        • 当然非层次化索引也可以用rename_axis重命名索引名。
        • rename方法用于修改列或者行索引标签,而不是索引名
        • 当不同层级的索引有相同的值的时候,这会造成混乱。
        • 当不同层级的索引有相同的值的时候,这会造成混乱--注意行索引的每一层的 A 都被改为了 T。
        • 一个问题:如果不同层级的索引的索引值有相同的值的时候,要想修改特定级别的索引的索引值(比如次级索引中的A,修改为a),需要如何修改?
        • 答:使用参数level=1指定需要修改的层级为次级索引
    • 常用索引型函数
      • 1. where函数
        • 当对条件为False的单元进行填充,不满足条件的行全部被设置为NaN
        • 注意和query的区别
        • where函数需要增加一个dropna()才会和query等价,通过这种方法筛选结果和[ ]操作符的结果完全一致。
        • [] 操作符--实际上是传入了布尔值索引。
        • 第一个参数con为布尔条件,第二个参数other为填充值
        • mask函数与where功能上相反,其余完全一致,即对条件为True的单元进行填充
        • query函数中的布尔表达式中,下面的符号都是合法的:行列索引名、字符串、and / not / or / & / | / ~ / not in / in /==/!=、四则运算符。
        • 实际上就是根据列值满足的条件筛选行---基本上和sql里的where子句对应。注意传入的参数是带引号的
    • 重复元素处理
      • 1. duplicated方法
        • 该方法返回了是否重复的布尔列表。
        • 可选参数keep默认为first,即首次出现设为不重复,若为last,则最后一次设为不重复,若为False,则所有重复项为False。
      • 2. drop_duplicates方法
        • 从名字上看出为剔除重复项,这在后面章节中的分组操作中可能是有用的,例如需要保留每组的第一个值:
        • 上边有些类似于mysql中按某列groupby之后,还能选择其他的非分组列。
        • 在传入多列时等价于将多列共同视作一个多级索引,比较重复项:
    • 抽样函数
    • 这里的抽样函数指的就是sample函数
    • 1. n为样本量
    • 以某一列为权重,这在抽样理论中很常见
    • 以某一列为权重,这在抽样理论中很常见--本质上是以这一列的列值为权重
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档