利用python进行数据分析-NumPy高级应用

1.ndarray对象的内部机理

NumPy的ndarray提供了一种将同质化数据块解释为多维数组对象的方式,ndarray如此强大的部分原因是所有数组对象都是数据块的一个跨度视图。ndarray内部由以下内容组成:

a.一个指向数组(一个系统内存块)的指针

b.数据类型或dtype

c.一个表示数组形状的元组;例如,一个10*5的数组,其形状为(10,5)

d.一个跨度元组,其中的整数指的是为了前进到当前维度下一个元素需要“跨度”的字节数;如,一个3*4*5的float(8个字节)数组,其跨度为(160,40,8)


2.NumPy数据类型体系

ints=np.ones(10,dtype=np.uint16)
floats=np.ones(10,dtype=np.float32)
print np.issubdtype(ints.dtype,np.integer)
print np.issubdtype(floats.dtype,np.floating)

结果为:

True
True

调用dtype的mro方法即可查看其所有的父类

print np.float64.mro()

结果为:

[, , , , , , ]

利用python进行数据分析-NumPy高级应用_第1张图片


3.高级重塑

假设有一个一维数组,我们希望将其重新排列为一个矩阵

arr=np.arange(8)
print arr
print arr.reshape((4,2))

结果为:

[0 1 2 3 4 5 6 7]
[[0 1]
 [2 3]
 [4 5]
 [6 7]]

多维数组也能被重塑

print arr.reshape((4,2)).reshape((2,4))

结果为:

[[0 1 2 3]
 [4 5 6 7]]

作为参数的形状其中一维可以是-1,它表示该维度的大小由数据本身推断而来

arr2=np.arange(15)
print arr2.reshape((5,-1))

结果为:

[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]]

由于数组的shape属性是一个元组,因此它可以被传入reshape

other_arr=np.ones((3,5))
print other_arr.shape
print arr2.reshape(other_arr.shape)

结果为:

(3L, 5L)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]

与reshape将一维数组转换为多维数组的运算过程相反的运算通常称为扁平化(flattening)或散开(raveling)

arr3=np.arange(15).reshape((5,3))
print arr3
print arr3.ravel()

结果为:

[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]]
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]

如果没有必要,ravel不会产生源数据的副本。flatten方法的行为类似于ravel,只不过它总是返回数据的副本

print arr3.flatten()

结果为:

[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]

数组可以被重塑或散开为别的顺序


4.C和Fortran顺序

默认情况下,NumPy数组是按行优先顺序创建的。在空间方面,意味着,对于一个二维数组,每行中的数据项是被存放在相邻内存位置上的。另一种顺序是列优先顺序,意味着每列中的数据项是被存放在相邻内存位置上的。

由于一些历史原因,行和列优先顺序又分别称为C和Fortran顺序。

arr4=np.arange(12).reshape((3,4))
print arr4
print arr4.ravel()
print arr4.ravel('F')

结果为:

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[ 0  1  2  3  4  5  6  7  8  9 10 11]
[ 0  4  8  1  5  9  2  6 10  3  7 11]

二维或更高数组的重溯过程比较令人费解。C和Fortran顺序的关键区别就是维度的行进顺序:

a.C/行优先顺序:先经过更高的维度(如,轴1会优先于轴0被处理)

b.Fortran/列优先顺序:后经过更高的维度(如,轴0会优先于轴1被处理)


5.数组的合并和拆分

numpy.concatenate可以按指定轴将一个由数组组成的列连接到一起

arr5=np.array([[1,2,3],[4,5,6]])
arr6=np.array([[7,8,9],[10,11,12]])
print np.concatenate([arr5,arr6],axis=0)
print np.concatenate([arr5,arr6],axis=1)

结果为:

[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
[[ 1  2  3  7  8  9]
 [ 4  5  6 10 11 12]]

对于常见的连接操作,NumPy提供了一些比较方便的方法(如vstack和hstack)。因此,上面的运算还可以表达为:

print np.vstack((arr5,arr6))
print np.hstack((arr5,arr6))

结果为:

[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
[[ 1  2  3  7  8  9]
 [ 4  5  6 10 11 12]]

与此相反,split用于将一个数组沿指定轴拆分为多个数组

from numpy.random import randn

arr7=randn(5,2)
print arr7
first,second,third=np.split(arr7,[1,3])
print first
print second
print third

结果为:

[[ 0.33316817 -0.50434988]
 [ 1.6748641   0.64469978]
 [ 0.1054192   0.80107941]
 [ 0.67531015  0.15332466]
 [ 1.33885961  2.0612464 ]]
[[ 0.33316817 -0.50434988]]
[[ 1.6748641   0.64469978]
 [ 0.1054192   0.80107941]]
[[ 0.67531015  0.15332466]
 [ 1.33885961  2.0612464 ]]

利用python进行数据分析-NumPy高级应用_第2张图片


5.堆叠辅助类:r_和c_

NumPy命名空间中有两个特殊的对象:r_和c_,他们可以是数组的堆叠操作变的简洁

arr8=np.arange(6)
arr9=arr8.reshape((3,2))
arr10=randn(3,2)
print np.r_[arr9,arr10]
print np.c_[np.r_[arr9,arr10],arr8]

结果为:

[[ 0.          1.        ]
 [ 2.          3.        ]
 [ 4.          5.        ]
 [ 1.41942797  0.28664832]
 [-0.17366714 -1.07803222]
 [ 0.16150609 -0.09420703]]
[[ 0.          1.          0.        ]
 [ 2.          3.          1.        ]
 [ 4.          5.          2.        ]
 [ 1.41942797  0.28664832  3.        ]
 [-0.17366714 -1.07803222  4.        ]
 [ 0.16150609 -0.09420703  5.        ]]

此外,它还可以将切片翻译为数组

print np.c_[1:6,-10:-5]

结果为:

[[  1 -10]
 [  2  -9]
 [  3  -8]
 [  4  -7]
 [  5  -6]]


6.元素的重复操作:tile和repeat

repeat会将数组中的各个元素重复一定次数,从而产生一个更大的数组

arr11=np.arange(3)
print arr11.repeat(3)

结果为:
[0 0 0 1 1 1 2 2 2]

默认情况下,如果传入的是一个整数,则各元素就都会重复那么多次。如果传入的是一组整数,则各元素就可以重复不同的次数

print arr11.repeat([2,3,4])

结果为:

[0 0 1 1 1 2 2 2 2]

对于多维数组,还可以让它们的元素沿指定轴重复

arr12=randn(2,2)
print arr12
print arr12.repeat(2,axis=0)

结果为:

[[-0.42963441  1.04916829]
 [ 0.25862366 -0.76362955]]
[[-0.42963441  1.04916829]
 [-0.42963441  1.04916829]
 [ 0.25862366 -0.76362955]
 [ 0.25862366 -0.76362955]]

如果没有设置轴向,则数组会被扁平化。同样,在对多维进行重复时,也可以传入一组整数,这样就会使各切片重复不同的次数

print arr12.repeat([2,3],axis=0)
print arr12.repeat([2,3],axis=1)

结果为:

[[-0.77124211  0.05274718]
 [-0.77124211  0.05274718]
 [-0.77421856  0.66942701]
 [-0.77421856  0.66942701]
 [-0.77421856  0.66942701]]
[[-0.77124211 -0.77124211  0.05274718  0.05274718  0.05274718]
 [-0.77421856 -0.77421856  0.66942701  0.66942701  0.66942701]]

tile的功能是沿指定轴向堆叠数组的副本。你可以形象地将其想象成“铺瓷砖”

print np.tile(arr12,2)

结果为:

[[ 0.78539826  0.47637034  0.78539826  0.47637034]
 [-0.8182709   0.09178917 -0.8182709   0.09178917]]

第二个参数是瓷砖的数量。对于标量,瓷砖是水平铺设的,而不是垂直铺设。它可以是一个表示“铺设”布局的元组

print np.tile(arr12,(2,1))
print np.tile(arr12,(3,2))

结果为:

[[-0.02208397  0.63182887]
 [ 2.32495598 -1.45611412]
 [-0.02208397  0.63182887]
 [ 2.32495598 -1.45611412]]
[[-0.02208397  0.63182887 -0.02208397  0.63182887]
 [ 2.32495598 -1.45611412  2.32495598 -1.45611412]
 [-0.02208397  0.63182887 -0.02208397  0.63182887]
 [ 2.32495598 -1.45611412  2.32495598 -1.45611412]
 [-0.02208397  0.63182887 -0.02208397  0.63182887]
 [ 2.32495598 -1.45611412  2.32495598 -1.45611412]]


7.花式索引的等价函数:take和put

获取和设置数组子集的一个办法是通过整数数组使用花式索引

arr13=np.arange(10)*100
inds=[7,1,2,6]
print arr13
print arr13[inds]

结果为:

[  0 100 200 300 400 500 600 700 800 900]
[700 100 200 600]

ndarray有两个方法专门用于获取和设置单个轴向上的选区

print arr13.take(inds)
arr13.put(inds,42)
print arr13
arr13.put(inds,[40,41,42,43])
print arr13

结果为:

[  0  42  42 300 400 500  42  42 800 900]
[  0  41  42 300 400 500  43  40 800 900]

要在其他轴上使用take,只需传入axis关键字即可

inds=[2,0,2,1]
arr14=randn(2,4)
print arr14
print arr14.take(inds,axis=1)

结果为:

[[-0.73988407  0.22688772 -0.39941488 -0.0557277 ]
 [ 0.35025622  1.37056291 -1.63300772 -0.90342322]]
[[-0.39941488 -0.73988407 -0.39941488  0.22688772]
 [-1.63300772  0.35025622 -1.63300772  1.37056291]]

put不接受axis参数,它只会在数组的扁平化版本(一维,C顺序)上进行索引。因此,在需要用其它轴向的索引设置元素时,最好还是使用花式索引


8.广播

广播指的是不同形状的数组之间的算术运算的执行方式

arr15=np.arange(5)
print arr15
print arr15*4

结果为:

[0 1 2 3 4]
[ 0  4  8 12 16]

在这个乘法运算中,标量值4被广播到其它所有的元素上

再来看个,可以通过减去列平均值的方式对数组的每一列进行距平化处理

arr16=randn(4,3)
print arr16
print arr16.mean(0)
demeaned=arr16-arr16.mean(0)
print demeaned
print demeaned.mean(0)

结果为:

[[ 1.05042619 -0.33072072 -0.49485782]
 [ 1.1650679   0.81910696  0.71711523]
 [ 0.43066235 -0.07393034  0.95870108]
 [ 0.98933099  0.28349482  0.65582962]]
[ 0.90887186  0.17448768  0.45919703]
[[ 0.14155433 -0.5052084  -0.95405484]
 [ 0.25619604  0.64461928  0.2579182 ]
 [-0.47820951 -0.24841802  0.49950405]
 [ 0.08045914  0.10900714  0.19663259]]
[ -2.77555756e-17   1.38777878e-17   2.77555756e-17]


你可能感兴趣的:(python)