Pandas入门系列(五)-- 索引对象

Python3数据科学汇总: https://blog.csdn.net/weixin_41793113/article/details/99707225 


 

## Reindexing Series and DataFrame

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

# series reindex

s1 = Series([1,2,3,4], index=['A','B','C','D'])
s1

s1.reindex(index=['F','B','C','D','E']) ##重开改变索引,并故意加多一个看发生什么

果然很震惊!原来第一个数据改成F找不到配的了,多出的E也是没有匹配上,大概可以猜出reindex的工作原理了,继续~

 

s1.reindex(index=['D','B','C','D','A'])

果然和预料之中,和你有多少索引无关,只要原来有这个索引就能找到值

 

s1.reindex(index=['A','B','C','D','E'], fill_value=10) ##找不到对应的索引就补充值为10

s2 = Series(['A','B','C'], index=[1,5,10]) #测试第二个样例Series
s2

s2.reindex(index=range(15),method='ffill')

## 生成0-15的索引,没出现的索引用前一个出现的索引补充

## 字母也可以补全

 

# reindex dataframe

df1 = DataFrame(np.random.rand(25).reshape([5,5]), index=['A','B','D','E','F'], columns=['c1','c2','c3','c4','c5'])
df1

生成0~1的随机数据 

 

df1.reindex(index=['A','B','C','D','E','F']) ##没有出现的索引

df1.reindex(columns=['c1','c2','c3','c4','c5','c6']) ##同理

df1.reindex(index=['A','B','C','D','E','F'],columns=['c1','c2','c3','c4','c5','c6'])

df1.reindex(index=['A','B'])

# Series and dataframe drop

s1

s1.drop('A') ##删除索引为A的数据

下面特殊情况,不过一般情况下,index是唯一的 

df1

df1.drop('c1', axis=1)

可以看出,df。drop()默认是按行删,即索引

 

多级Index

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
s1 = Series(np.random.randn(6), index=[['1','1','1','2','2','2'],['a','b','c','a','b','c']])
s1

 

type(s1['1']) #可以看出多级索引里面的索引也是一个Series

可以看成是个二维数组,2个索引都用上就是数据了

s1['1']['a']

s1[:,'a']

上面类比二维数组来学,没啥难度

 

df1 = s1.unstack() #变成dataframe
df1

df2 = DataFrame([s1['1'],s1['2']])
df2

df1.stack()

s2 = df1.unstack()
s2

s2 = df1.T.unstack()
s2

 

df = DataFrame(np.arange(16).reshape(4,4), index=[['a','a','b','b'],[1,2,1,2]], columns=[['BJ','BJ','SH','GZ'],[8,9,8,8]])
df

df['BJ'][8]

 

 

一. 索引对象

在之前介绍的Series和DataFrame结构中,我们已经接触到了索引对象,它是pandas的重要组成部分。pandas定义了Index类来表示基本索引对象,想要获取数据的索引对象,只需调用数据的index属性即可index=df.index
这里有几点需要强调:

1. 索引是可以重复的

虽然很多时候都要求索引唯一,但这并不是强制的。我们可以使用索引对象is_unique属性,来判断索引是否唯一。

d=DF({'A':[1,2,3,4,5],'B':[6,7,8,9,10]},index=[1,1,2,2,3])
print(d)
print(d.index.is_unique)

Out[1]:
   A   B
1  1   6
1  2   7
2  3   8
2  4   9
3  5  10

False

2. 索引一旦确立就不可以再修改

索引是不可以修改的,但是可以全部重置。怎么理解呢?就是不可以修改索引的任何一部分,但是可以全部替换掉。索引的不可修改性十分重要,因为只有这样才能保证数据结构间安全共享(eg.自动对齐)。
那么如何替换掉所有的索引呢?有4种方法:

  • reset_index:替换旧索引,新的索引按0,1,2,3,4.....递增
  • Series/DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill=' ')
  • level:要删除哪一级索引(多重索引)
  • drop:False则将旧索引变成列,True则删除旧索引
  • inplace:是否在原数据中修改
  • col_level:如果列是多重标签,旧索引名插入到哪一层
  • col_fill:如果列是多重标签,剩下的标签名是什么
  • set_index :将dataframe其中某列作为索引
  • DataFrame.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False)
  • keys:要置为索引的列标签(列表)
  • drop:True设置为新索引的列被删除,False被保留
  • append:True保留原索引,keys中的列变为下一级索引
  • inplace:是否在原数据中修改
  • verify_integrity:True检测新的索引是否重复,重复则报错。
  • reindex:设置新索引, 新索引中不存在对应的数据,则将数据设为nan
  • reindex更多的不是修改pandas对象的索引,而只是修改索引的顺序,如果修改的索引不存在就会使用默认的None代替此行。
  • Series/Panel/DataFrame.reindex(labels=None, index=None, columns=None, axis=None, method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None)
  • 前4个参数:传入新的索引数组,说明要修改行索引还是列标签。
  • 举个例子:我们看到,旧索引是[0,1,2,3,4],替换的新索引是[1,2,3,4,5,6],2个索引的交集被保留下来,新索引中不存在的标签0被删除,同时引入了新索引中的标签[5,6],数据为NAN
d=DF({'A':[1,1,3,4,5],'B':[6,7,8,9,10]})
print(d)
d=d.reindex([1,2,3,4,5,6])
print(d)

Out[2]:
   A   B
0  1   6
1  1   7
2  3   8
3  4   9
4  5  10
     A     B
1  1.0   7.0
2  3.0   8.0
3  4.0   9.0
4  5.0  10.0
5  NaN   NaN
6  NaN   NaN

method:新引入的索引标签的数据填充方法。pad / ffill向前保持一致;backfill / bfill向后保持一致;nearest和最近保持一致。

d=DF({'A':[1,1,3,4,5],'B':[6,7,8,9,10]},index=[0,1,3,4,5])
print(d)
d=d.reindex([1,2,3,4,5,6],method='pad')
print(d)

Out[3]:
   A   B
0  1   6
1  1   7
3  3   8
4  4   9
5  5  10
   A   B
1  1   7
2  1   7
3  3   8
4  4   9
5  5  10
6  5  10

fill_value:新引入的索引标签的数据填充值。

  • 直接赋值:直接将索引赋值给index变量,长度要和数据一致
data=pd.DataFrame({'A':[1,2,],'B':[0,0,],'C':[7,8]})
data.index=['a','b']

Out:
   A  B  C
a  1  0  7
b  2  0  8

二. 多重索引对象

多重索引(hierarchical indexing)是pandas的一个重要的功能,它可以在一个轴上有多个(两个以上)的索引,这就表示着,它能够以低维度形式来表示高维度的数据。注意,这里我说的是轴,这就意味着,多重索引可以是行索引,也可以是列索引。

1. 创建多重行索引

  1. 显式创建多重行索引:利用pandas.MultiIndex对象
    MultiIndex是pandas中标准的多重索引类,使用时只需将该对象赋值给基本结构的index参数即可。那么,我们如何创建这个MultiIndex对象呢?主要有以下几种方法:
  • 从数组构建:MultiIndex.from_arrays(arrays, sortorder=None, names=None)
  • 从元组构建:MultiIndex.from_tuples(tuples, sortorder=None, names=None)
  • 从数组交差配对构建:MultiIndex.from_product(iterables, sortorder=None, names=None)
    其中,第一个参数是索引结构,names是索引名,举个例子:
#注意观察从数组构建,与从交叉迭代构建的区别!!
arr=[['a','b'],[1,2]]
ind=pd.MultiIndex.from_arrays(arr,names=['alpha','number'])
data=pd.DataFrame({'A':[1,2,],'B':[0,0,],'C':[7,8]},index=ind)
print(data)

Out:
              A  B  C
alpha number         
a     1       1  0  7
b     2       2  0  8


arr=[['a','b'],[1,2]]
ind=pd.MultiIndex.from_product(arr,names=['alpha','number'])#交叉迭代
data=pd.DataFrame({'A':[1,2,3,4],'B':[0,0,5,6],'C':[7,8,0,0]},index=ind)
print(data)

Out:
              A  B  C
alpha number         
a     1       1  0  7
      2       2  0  8
b     1       3  5  0
      2       4  6  0
  1. 隐式创建多重行索引
  • 利用set_index()函数添加索引
    更多的时候我们不是自己创建数据结构,而是从文件中读取数据,然后自己设定索引列。还记得之前介绍set_index()函数的时候,提到过一个参数append,它被设置为True的时候,原索引不变,指定列被设置为原索引的下一级索引,我们可以利用这个特点,构造多重索引。
    举个例子:可以看到,栗子中的B列变成了2级索引。
data=pd.DataFrame({'A':[1,2,3],'B':[0,0,4],'C':[7,8,5]})
data.index.name='index'
data.set_index(keys=['B'],append=True,inplace=True)
print(data)

Out:
         A  C
index B      
0     0  1  7
1     0  2  8
2     4  3  5
  • 构造数据时,直接传入多个索引数组
    直接上栗子,这个很好理解
data=pd.DataFrame({'A':[1,2,3],'B':[0,0,4],'C':[7,8,5]},index=[['a','a','b'],[1,2,3]])
print(data)

Out:
     A  B  C
a 1  1  0  7
  2  2  0  8
b 3  3  4  5

2. 创建多重列索引

直接使用MultiIndex对象显示创建多重列索引。

arr=[['A','A','C'],['a','b','a']]
ind=pd.MultiIndex.from_arrays(arr,names=['letter','number'])
data=pd.DataFrame([[1,2,3],[0,0,4],[7,8,5]],columns=ind)
print(data)

Out:
letter  A     C
number  a  b  a
0       1  2  3
1       0  0  4
2       7  8  5

3.多重索引对象下的索引操作

之前讲pandas基本数据结构的时候,我们提到,常用的索引操作方式主要有以下几种:

  • 点字符 :访问列
  • 中括号 [ ]
  • loc[ ] :基于标签索引,可以批量选取
  • iloc[ ] :基于位置索引,可以批量选取
  • at[ ] : 基于标签索引,只能选取一个元素
  • iat[ ] : 基于位置索引,只能选取一个元素

在多重索引中也同样适用,而且使用方法基本雷同。这个时候可能会有人问,如何选择子索引呢?这个很简单,下面我们一起来看:
示例数据:

       A     C
       a  b  a
1 i    1  2  3
  ii   0  0  4
3 iii  7  8  5
  1. 索引元组:如果想要选取最外层索引,和普通单索引对象没区别。若是想要选取多层索引,就要使用元组的括号把索引包裹起来,我们看个栗子。
#只选最外层
print(data['A'])

Out:
       a  b
1 i    1  2
  ii   0  0
3 iii  7  8

#选列多层
print(data[ ('A','a') ])

Out:
1  i      1
   ii     0
3  iii    7

#行列都来个多层
print(data.loc[ (1,'ii') , ('A','a') ])

Out:
0

2.切片
多重索引也支持切片操作,只需用元组括号包裹多层的索引就可以了。

print(data.loc[(1,'ii'):,('A','a')])
Out:
1  ii     0
3  iii    7

另外,slice(None), 是Python中的切片操作,这里用来选择任意的id,要注意!不能使用‘:’来指定任意index,‘:’用来指定dataframe任意的列

print(data.loc[(slice(None),'ii')])
Out:
       A     C
       a  b  a
  ii   0  0  4

3.点字符
多重索引也支持点字符访问列,可以每一级使用一个点字符。

print(data.A.a)

Out:
1  i      1
   ii     0
3  iii    7

4.删除多重索引

使用pandas.MultiIndex.droplevel()函数,可以删除指定level的行索引。

data.index=data.index.droplevel(0)
print(data)

Out:
     A     C
     a  b  a
i    1  2  3
ii   0  0  4
iii  7  8  5
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值