5.2.4 整数索引
在pandas
对象使用上用整数索引时经常会产生歧义,这是因为它和在列表,元祖等Python内建数据结构上进行索引有些不同。下面的代码就会发生错误
In [20]: ser=pd.Series(np.arange(3.))
In [21]: ser
Out[21]:
0 0.0
1 1.0
2 2.0
dtype: float64
In [24]: ser[-1]
In [25]: Traceback (most recent call last):
File "/Applications/Spyder.app/Contents/Resources/lib/python3.9/pandas/core/indexes/range.py", line 351, in get_loc
return self._range.index(new_key)
ValueError: -1 is not in range
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<ipython-input-24-44969a759c20>", line 1, in <module>
ser[-1]
File "/Applications/Spyder.app/Contents/Resources/lib/python3.9/pandas/core/series.py", line 853, in __getitem__
return self._get_value(key)
File "/Applications/Spyder.app/Contents/Resources/lib/python3.9/pandas/core/series.py", line 961, in _get_value
loc = self.index.get_loc(label)
File "/Applications/Spyder.app/Contents/Resources/lib/python3.9/pandas/core/indexes/range.py", line 353, in get_loc
raise KeyError(key) from err
在上面的例子中,pandas可以退回到整数索引,但是这样的方式难免会引起一些错误。
假设我们有一个索引,它包含了0,1,2,但是要猜测用户所需要的索引方法(标签索引还是位置索引)是很难的。
然而,非整数索引,不会有潜在的歧义.
In [26]: ser2=pd.Series(np.arange(3.),index=['a','b','c'])
In [27]: ser2[-1]
Out[27]: 2.0
为了保持一致性,如果我们有一个包含整数的轴索引,数据选择时请始终使用标签索引。
为了更精确的处理,可以使用loc
或者iloc
。
In [28]: ser[:1]
Out[28]:
0 0.0
dtype: float64
In [29]: ser.loc[:1]
Out[29]:
0 0.0
1 1.0
dtype: float64
In [30]: ser.iloc[:1]
Out[30]:
0 0.0
dtype: float64
5.2.5 算术和数据对齐
这一节的内容并不难理解。
当你将两个有索引的数据相加时,如果存在某个索引对不相同,则返回结果的索引将是索引对的并集。对数据库用户来说,这个特性类似于标签的自动外连接(outer join)。让我们看一下下面的示例。
In [31]: s1=pd.Series([7.3,-2.5,3.4,1.5],index=['a','c','d','e'])
In [32]: s2=pd.Series([-2.1,3.6,-1.5,4,3.1],
...: index=['a','c','e','f','g'])
In [33]: s1+s2
Out[33]:
a 5.2
c 1.1
d NaN
e 0.0
f NaN
g NaN
dtype: float64
索引重合的地方计算没问题,不重合的地方会返回NaN。
In [41]: df1=pd.DataFrame(np.arange(9.).reshape((3,3)),columns=list('bcd'),
...: index=['Ohio','Texas','Colorado'])
In [42]: df2=pd.DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),
...: index=['Utah','Ohio','Texas','Oregon'])
In [43]: df1
Out[43]:
b c d
Ohio 0.0 1.0 2.0
Texas 3.0 4.0 5.0
Colorado 6.0 7.0 8.0
In [44]: df2
Out[44]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0
In [45]: df1+df2
Out[45]:
b c d e
Colorado NaN NaN NaN NaN
Ohio 3.0 NaN 6.0 NaN
Oregon NaN NaN NaN NaN
Texas 9.0 NaN 12.0 NaN
Utah NaN NaN NaN NaN
由于'c'和 'e' 列并不是两个DataFrame共有的列,这两列中产生了缺失值。对于行标签不同的DataFrame对象也是如此。
如果你将两个行或列完全不同的DataFrame对象相加,结果将全部为空。
In [1]: import pandas as pd
In [2]: df1=pd.DataFrame({'A':[1,2]})
In [3]: df2=pd.DataFrame({'B':[3,4]})
In [4]: df1
Out[4]:
A
0 1
1 2
In [5]: df2
Out[5]:
B
0 3
1 4
In [6]: df1-df2
Out[6]:
A B
0 NaN NaN
1 NaN NaN
5.2.5.1 使用填充值的算术方法
在两个不同的索引化对象之间进行算数操作时,会用到使用特殊填充值,比如当轴标签在一个对象中不存在时,可以把缺失值填充为0。
In [16]: df1=pd.DataFrame(np.arange(12.).reshape((3,4)),
...: columns=list('abcd'))
In [17]: df2=pd.DataFrame(np.arange(20.).reshape((4,5)),
...: columns=list('abcde'))
In [18]: df2.loc[1,'b']=np.nan
In [19]: df1
Out[19]:
a b c d
0 0.0 1.0 2.0 3.0
1 4.0 5.0 6.0 7.0
2 8.0 9.0 10.0 11.0
In [20]: df2
Out[20]:
a b c d e
0 0.0 1.0 2.0 3.0 4.0
1 5.0 NaN 7.0 8.0 9.0
2 10.0 11.0 12.0 13.0 14.0
3 15.0 16.0 17.0 18.0 19.0
将这些df添加到一起会导致在一些不重叠的位置出现NA值。
In [21]: df1+df2
Out[21]:
a b c d e
0 0.0 2.0 4.0 6.0 NaN
1 9.0 NaN 13.0 15.0 NaN
2 18.0 20.0 22.0 24.0 NaN
3 NaN NaN NaN NaN NaN
表5.5列出了Series和DataFrame的算术方法。这些方法中的每一个都有一个以r开头的副本。
表5.5
211007
5.2.5.2 DataFrame和Series之间的操作
DataFrame和Series之间的算数操作与Numpy中不同纬度数组之间的操作类似。
In [13]: arr=np.arange(12.).reshape((3,4))
In [14]: arr
Out[14]:
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
In [15]: arr[0]
Out[15]: array([0., 1., 2., 3.])
In [16]: arr-arr[0]
Out[16]:
array([[0., 0., 0., 0.],
[4., 4., 4., 4.],
[8., 8., 8., 8.]])
在上面的例子里,当我们从arr中减去arr[0]时,减法在每一行都进行了操作。这就是所谓的广播机制。DataFrame和Series之间的操作是类似的。