3.4 Pandas数值计算方法
《Python数据科学手册》读书笔记:
NumPy 的基本能力之一是快速对每个元素进行运算,既包括基本算术运算(加、减、乘、除),也包括更复杂的运算。Pandas集成了Numpy的功能,也实现了一些高效技巧:
- 对于一元计算,输出结果保留行索引和列标签
- 对于二元计算,自动对齐索引进行计算
3.4.1 通用函数:保留索引
In[1] : import pandas as pd
import numpy as np
In[2] : rng = np.random.RandomState(42) # 伪随机数生成器,和numpy.random.seed()类似
ser = pd.Series(rng.randint(0, 10, 4))
ser
Out[2]: 0 6
1 3
2 7
3 4
dtype: int64
In[3] : df = pd.DataFrame(rng.randint(0, 10, (3, 4)),
columns=['A', 'B', 'C', 'D'])
Out[3]: A B C D
0 6 9 2 6
1 7 4 3 7
2 7 2 5 4
如果对这两个对象的其中一个使用NumPy 通用函数,生成的结果是另一个保留索引的Pandas 对象:
In[4] : np.exp(ser)
Out[4]: 0 403.428793
1 20.085537
2 1096.633158
3 54.598150
dtype: float64
3.4.2 通用函数:索引对齐
当在两个Series 或DataFrame 对象上进行二元计算时,Pandas 会在计算过程中对齐两个对象的索引.
1. Series索引对齐
例:假如你要整合两个数据源的数据,其中一个是美国面积最大的三个州的面积数据,另一个是美国人口最多的三个州的人口数据:
In[6] : area = pd.Series({'Alaska': 1723337, 'Texas': 695662,'California': 423967}, name='area')
population = pd.Series({'California': 38332521, 'Texas': 26448193,'New York': 19651127}, name='population')
In[7] : population / area
Out[7]: Alaska NaN
California 90.413926
New York NaN
Texas 38.018740
dtype: float64
结果数组的索引是两个输入数组索引的并集.对于缺失位置的数据,Pandas 会用NaN 填充,表示“此处无数”.如果NaN值不是我们想要的数值,那么可以用我们想到的数值进行填充,需要将运算符换成对应的方法。
In[9] : A = pd.Series([2, 4, 6], index=[0, 1, 2])
B = pd.Series([1, 3, 5], index=[1, 2, 3])
A + B
Out[9]: 0 NaN # 虽然索引不对应,但仍保留索引,用NaN填充value
1 5.0
2 9.0
3 NaN
dtype: float64
In[10] : A.add(B, fill_value=0)
Out[10]: 0 2.0
1 5.0
2 9.0
3 5.0
dtype: float64
2. DataFrame索引对齐
在计算两个DataFrame 时,类似的索引对齐规则也同样会出现在共同(并集)列中:
In[11] : A = pd.DataFrame(rng.randint(0, 20, (2, 2)),
columns=list('AB')) # list(str)
A
Out[11]: A B
0 1 11
1 5 1
In[12]: B = pd.DataFrame(rng.randint(0, 10, (3, 3)),columns=list('BAC'))
B
Out[12]: B A C
0 4 0 9
1 5 8 0
2 9 2 6
In[13]: A + B # 二维数组与三维数组相加
Out[13]: A B C
0 1.0 15.0 NaN
1 13.0 6.0 NaN
2 NaN NaN NaN
索引顺序不同,但输出结果会自动按顺序排列
3.4.3 通用函数:DataFrame与Series的运算
我们经常需要对一个DataFrame 和一个Series 进行计算,行列对齐方式与之前类似。。也就是说,DataFrame 和Series 的运算规则,与NumPy 中二维数组与一维数组的运算规则是一样的。
In[15]: A = rng.randint(10, size=(3, 4))
A
Out[15]: array([[3, 8, 2, 4],
[2, 6, 4, 8],
[6, 1, 3, 8]])
In[16] : A - A[0] # 减去第一行数据,根据广播规则,整体减去
Out[16]: array([[ 0, 0, 0, 0],
[-1, -2, 2, 4],
[ 3, -7, 1, 4]])
如果想按列计算,那么通过axis参数设置:
In[18]: df.subtract(df['R'], axis=0)
Out[18]: Q R S T
0 -5 0 -6 -4
1 -4 0 -2 2
2 5 0 2 7
这些行列索引的保留与对齐方法说明Pandas 在运算时会一直保存这些数据内容,从而避免在处理数据类型有差异和/ 或维度不一致的NumPy 数组时可能遇到的问题。
注:RandomState的用法:【数据处理】numpy.random.RandomState的用法