5.1.3 索引对象
pandas中的索引对象是用于存储轴标签和其他元数据的(例如轴名称或标签)。在构造Series或DataFrame时,所使用的任意数组或标签序列都可以在内部转换为索引对象:
obj = pd.Series(range(3), index=['a', 'b', 'c'])
index = obj.index
print(index)
print(index[1:])
Index(['a', 'b', 'c'], dtype='object')
Index(['b', 'c'], dtype='object')
索引对象是不可变的,因此用户是无法修改索引对象的:
index[1] = 'd' # TypeError
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
in ()
----> 1 index[1] = 'd' # TypeError
/usr/local/lib/python3.6/dist-packages/pandas/core/indexes/base.py in __setitem__(self, key, value)
3936
3937 def __setitem__(self, key, value):
-> 3938 raise TypeError("Index does not support mutable operations")
3939
3940 def __getitem__(self, key):
TypeError: Index does not support mutable operations
不变性使得在多种数据结构中分享索引对象更为安全:
labels = pd.Index(np.arange(3))
print(labels)
print("-"*50)
obj2 = pd.Series([1.5, -2.5, 0], index=labels)
print(obj2)
print("-"*50)
print(obj2.index is labels)
Int64Index([0, 1, 2], dtype='int64')
--------------------------------------------------
0 1.5
1 -2.5
2 0.0
dtype: float64
--------------------------------------------------
True
一些用户并不经常利用索引对象提供的功能,但是因为一些操作会产生包含索引化数据的结果,理解索引如何工作还是很重要的。
除了类似数组,索引对象也像一个固定大小的集合:
print(frame3)
print("-"*50)
print(frame3.columns)
print("-"*50)
print('Ohio' in frame3.columns)
print("-"*50)
print(2002 in frame3.index)
print(2003 in frame3.index)
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
--------------------------------------------------
Index(['Nevada', 'Ohio'], dtype='object', name='state')
--------------------------------------------------
True
--------------------------------------------------
True
False
与Python集合不同,pandas索引对象可以包含重复标签:
dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])
print(dup_labels)
print(dup_labels.unique())
print('|'.join(dup_labels.unique()))
Index(['foo', 'foo', 'bar', 'bar'], dtype='object')
Index(['foo', 'bar'], dtype='object')
foo|bar
根据重复标签进行筛选,会选取所有重复标签对应的数据。
每个索引都有一些集合逻辑的方法和属性,这些方法和属性解决了关于它所包含的数据的其他常见问题。下表总结了这些方法和属性中常用的一部分。
方法 | 描述 |
---|---|
append | 将额外的索引对象粘贴到原索引后,产生一个新的索引 |
difference | 计算两个索引的差集 |
intersection | 计算两个索引的交集 |
union | 计算两个索引的并集 |
isin | 计算表示每一个值是否在传值容器中的布尔数组 |
delete | 将位置i的元素删除,并产生新的索引 |
drop | 根据传参删除指定索引值,并产生新的索引 |
insert | 在位置i插入元素,并产生新的索引 |
is monotonic | 如果索引序列递增则返回True |
Is unique | 如果索引序列唯一则返回True |
unique | 计算索引的唯一值序列 |
5.2 基本功能
接下来将会指引了解与Series或DataFrame中数据交互的基础机制。后续的内容中会更为深入地讲解使用pandas进行数据分析和操作的主题。
5.2.1 重建索引
reindex是pandas对象的重要方法,该方法用于创建一个符合新索引的新对象。考虑下面的例子:
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
obj
d 4.5
b 7.2
a -5.3
c 3.6
dtype: float64
Series调用reindex方法时,会将数据按照新的索引进行排列,如果某个索引值之前并不存在,则会引入缺失值:
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
obj2
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
对于顺序数据,比如时间序列,在重建索引时可能会需要进行插值或填值。method
可选参数允许使用诸如ffill
等方法在重建索引时插值,ffill
方法会将值前向填充:
obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
obj3
obj3.reindex(range(6), method='ffill')
0 blue
1 blue
2 purple
3 purple
4 yellow
5 yellow
dtype: object
在DataFrame中,reindex可以改变行索引、列索引,也可以同时改变二者。当仅传入一个序列时,结果中的行会重建索引:
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'c', 'd'],
columns=['Ohio', 'Texas', 'California'])
frame
Ohio | Texas | California | |
---|---|---|---|
a | 0 | 1 | 2 |
c | 3 | 4 | 5 |
d | 6 | 7 | 8 |
frame2 = frame.reindex(['a', 'b', 'c', 'd'])
frame2
Ohio | Texas | California | |
---|---|---|---|
a | 0.0 | 1.0 | 2.0 |
b | NaN | NaN | NaN |
c | 3.0 | 4.0 | 5.0 |
d | 6.0 | 7.0 | 8.0 |
列可以使用columns关键字重建索引:
states = ['Texas', 'Utah', 'California']
frame.reindex(columns=states)
Texas | Utah | California | |
---|---|---|---|
a | 1 | NaN | 2 |
c | 4 | NaN | 5 |
d | 7 | NaN | 8 |
下表是reindex方法的参数列表。
参数 | 描述 |
---|---|
index | 新建作为索引的序列, 可以是索引实例或任意其他序列型Python数据结构索引使用时无须复制 |
method | 插值方式;'ffill'为前向填充,而'bfill'是后向填充 |
fill_value | 通过重新索引引入缺失数据时使用的替代值 |
limit | 当前向或后向填充时,所需填充的最大尺寸间隙(以元素数量) |
tolerance | 当前向或后向填充时, 所需填充的不精确匹配下的最大尺寸间隙(以绝对数字距离) |
level | 匹配 MultiIndex级别的简单索引;否则选择子集 |
copy | 如果为True,即使新索引等于旧索引,也总是复制底层数据; 如果是 False,则在索引相同时不要复制数据 |
更深入地探索时,可以使用loc进行更为简洁的标签索引,许多用户更倾向于使用这种方式:
# 不增加数据内容的,不会产生报错
print(frame.loc[['a','c','d'],['Ohio','Texas']])
print("-"*50)
# 会有后期功能不可用的警告(提示使用reindex)
print(frame.loc[['a', 'b', 'c', 'd'], states])
Ohio Texas
a 0 1
c 3 4
d 6 7
--------------------------------------------------
Texas Utah California
a 1.0 NaN 2.0
b NaN NaN NaN
c 4.0 NaN 5.0
d 7.0 NaN 8.0
/usr/local/lib/python3.6/dist-packages/pandas/core/indexing.py:1494: FutureWarning:
Passing list-likes to .loc or [] with any missing label will raise
KeyError in the future, you can use .reindex() as an alternative.
See the documentation here:
https://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike
return self._getitem_tuple(key)
欢迎关注我的微信公众号一起交流!