利用Python进行数据分析(三)
NumPy基础
还是接着看NumPy,前面说到如何创建ndarray,如何使用切片,整数,索引来取的所需的数据,这节我们再来看看取得数据后,如何进行简单的处理下。
数组转置和轴对换
共有三种:
1.简单的T属性,二维数组对换。
2.transpose方法,指明哪些轴需要按照什么顺序转置。
3.swapaxes方法,只接受一堆轴编号,这两个轴对换。
arr = np.array([[1,2,3],[4,5,6]])
arr
out:array([[1, 2, 3],
[4, 5, 6]])
arr.T
out:array([[1, 4],
[2, 5],
[3, 6]])
np.dot(arr.T,arr)
out:array([[17, 22, 27],
[22, 29, 36],
[27, 36, 45]])
需要dot方法来计算矩阵内积X^TX 如果直接X.T*X会得到之前矢量化式的结果当然这个数组是2行3列,不能*。
那这个dot矩阵内积怎么算呢?如下:
array=([[1*1+4*4,1*2+4*5,1*3+4*6],
[2*1+5*4,2*2+5*5,2*3+5*6],
[3*1+6*4,3*2+6*5,3*3+6*6]])
能不能再具体解释呢?
其实就是第一个arr.T的m行分别乘以arr的n列得到新数组的(m,n)位置。如新数组的(0,1)即为arr.T的0行[1,4]分别乘以arr的1列2,5,即1*2+4*5=22。(这段话可能对不了解矩阵内积的同学有点帮助。)
arr = np.arange(16).reshape((2,2,4))
arr
out:array([[0,1,2,3],
[4,5,6,7],
[8,9,10,11],
[12,13,14,15]])
arr.transpose((1,0,2))
out:
array([[[0,1,2,3],
[4,5,6,7]],
[[8,9,10,11],
[12,13,14,15]]])
transpose是指明转置的顺序,arr.transpose(1,0,2)的意思就是0轴1轴对调,2轴不变。所以把0123,4567,891011,12131415,分别看成4个整体再转置即可。
结果是array([[[0,1,2,3],
[8,9,10,11]],
[[4,5,6,7],
[12,13,14,15]]])
swapaxes接受一对轴编号 然后互换。(也是返回源数据的视图,不会复制数据)
arr
out:
array([[[0,1,2,3],
[4,5,6,7]],
[[8,9,10,11],
[12,13,14,15]]])
arr.swapaxes(1,2)
#0轴不变 1,2轴换
out:array([[[0,4],
[1,5],
[2,6],
[3,7]],
[[8,12],
[9,13],
[10,14],
[11,15]]])
通用函数:快速的元素级数数组函数
ufunc是一种对ndarray中的数据执行元素级运算的函数。
列举一个modf函数,
arr = randn(7)*5
np.modf(arr)
out:(array([-0.6808,0.0636,-0.386,0.1393,-0.8806,09363,-0.883]),array([-2.,4.,-3.,5.,-3.,3.,-6.]))
modf函数是将整数部分和小数部分分别作为数组返回。其他的如下表,建议都尝试使用熟悉一下。
[图片上传失败...(image-12b2b4-1512618323155)]
[图片上传失败...(image-d5431a-1512618323155)]
利用数组进行数据处理
NumPy数组使你可以将许多种数据处理任务表述为简洁的数组表达式(否则需要编写循环)。用数组表达式代替循环的做法,通常被称为矢量化。一般来说,矢量化数组运算要比等价的纯Python方式快上一两个数量级(甚至更多),尤其是各种数值计算。在后面内容中(见第12章)我将介绍广播,这是一种针对矢量化计算的强大手段。
假设我们想要在一组值(网格型)上计算函数sqrt(x2+y2)。np.meshgrid函数接受两个一维数组,并产生两个二维矩阵(对应于两个数组中所有的(x,y)对):
import matplotlib.pyplot as plt
points = np.arange(-5,5,0.01)#1000个间隔相等的点
xs,ys = np.meshgrid(points,points)
z = np.sqrt(xs**2 + ys**2)
plt.imshow(z,cmap=plt.cm.gray)
plt.colorbar()
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")
plt.show()
结果图如下:
[图片上传失败...(image-622d0a-1512618323155)]
右边的竖条的含义是灰度所代表的值。可以明显的看到有一个一个的圆组成,且在第500(滑稽)个点附近最小。
主要是通过ndarry去矢量化运算,不需要使用循环。如果是java你应该怎么做?你需要去写一个循环,设置个i值逐个对数组取值然后操作。
将条件逻辑表述为数组运算
numpy.where函数是三元表达式x if condition else y的矢量化版本。假设我们有一个布尔数组和两个值数组:
xarr=np.array([1.1,1.2,1.3,1.4,1.5])
yarr=np.array([2.1,2.2,2.3,2.4,2.5])
cond=np.array([True,False,True,True,False])
假设我们想要做到根据cond,取xarr或者yarr的值:当cond中的值为True时,选取xarr的值,否则从yarr中选取。列表推导式的写法应该如下所示:
result=[(x if c else y)
for x,y,c in zip(xarr,yarr,cond)]
#注意顺序哈,如果c为True输出x否则输出y。
out:result
[1.1000000000000001,2.2000000000000002,1.3,1.3999999999999999,2.5]
存在两个问题:1,纯Python,运行较慢。
2,不能用于多维数组。
用np.where
result=np.where(cond,xarr,yarr)
result
out:array([1.1,2.2,1.3,1.4,2.5])
np.where(arr > 0,2,-2)的含义就是将arr中大于0的值替换为2,小于等于0的替换为-2。简洁!
你甚至还能嵌套成更为复杂的where表达式:
np.where(cond1 & cond2,0,
np.where(cond1,1,
np.where(cond2,2,3)))
Cond1\Cond2 | True | False |
---|---|---|
True | 0 | 1 |
False | 2 | 3 |
在这个特殊的例子中,我们还可以利用“布尔值在计算过程中可以被当做0或1处理”这个事实,所以还能将其写成下面这样的算术运算(虽然看上去有点神秘):
result=1*(cond1-cond2)+2*(cond2&-cond1)+3*-(cond1 I cond2)
总结:如开头所言,这次主要是对数组级的矢量化操作,一些常用的ufunc函数,np.where取代循环以达到更快速,更优秀的处理结果。
个人微信公众号:BrainZou