Numpy 是 Python 数据分析的基础,很多有关Python数据分析都是建立在其之上。

1 ndarray

整个 numpy 的基础是 ndarray (n dimensional array),表示同一元素组成的多维数组。

  • dtype 数据类型
  • shape 由N个正整数组成的元组,每一个元素代表了每一维的大小
  • axes 数组的维数为轴,轴的数量为秩(rank) Numpy 数组是不变的,一旦创建,就不可与改变

In [1]:
import numpy as np
a = np.array([1,2,3])
print a


[1 2 3]

In [2]:
type(a)


Out[2]:
numpy.ndarray

In [3]:
type(a)


Out[3]:
numpy.ndarray

In [4]:
a.dtype


Out[4]:
dtype('int32')

In [6]:
print a.ndim
print a.size
print a.shape


1
3
(3L,)

创建二维数组


In [8]:
b = np.array([[1.3,2.4],[0.3,4.1]])
print b.dtype
print b.ndim
print b.size
print b.shape


float64
2
4
(2L, 2L)

创建数组既可以通过list也可以通过tuple,也可以listtuple混合使用


In [2]:
import numpy as np
c = np.array([[1,2,3],[4,5,6]])
d = np.array([(7,8,9),(10,11,12)])
e = np.array([[13,14],(12,31),[12,21]])
print c
print d
print e


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

Numpy 自带了若干数组创建方法


In [3]:
np.zeros((3,3))


Out[3]:
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

In [4]:
np.ones((3,3))


Out[4]:
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

In [5]:
np.arange(4,10)


Out[5]:
array([4, 5, 6, 7, 8, 9])

In [6]:
np.arange(0,12,3)


Out[6]:
array([0, 3, 6, 9])

In [7]:
np.arange(0,6,0.6)


Out[7]:
array([ 0. ,  0.6,  1.2,  1.8,  2.4,  3. ,  3.6,  4.2,  4.8,  5.4])

In [8]:
np.arange(0,12).reshape(3,4)


Out[8]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

In [9]:
np.linspace(0,10,5)


Out[9]:
array([  0. ,   2.5,   5. ,   7.5,  10. ])

In [10]:
np.linspace(0,10,5,endpoint=True)


Out[10]:
array([  0. ,   2.5,   5. ,   7.5,  10. ])

In [11]:
np.linspace(0,10,5,endpoint=False)


Out[11]:
array([ 0.,  2.,  4.,  6.,  8.])

In [12]:
np.random.random(3)


Out[12]:
array([ 0.20130582,  0.47024921,  0.51813952])

In [13]:
np.random.random((3,4))


Out[13]:
array([[ 0.02214925,  0.63808889,  0.30278891,  0.39861784],
       [ 0.46047649,  0.71827545,  0.99090554,  0.59167459],
       [ 0.60618896,  0.69980344,  0.96309435,  0.02424105]])

2 运算操作

算术运算


In [1]:
import numpy as np
a = np.arange(4)
print a 
print a+4
print a*2


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

In [2]:
b = np.arange(4,8)
print b
print a + b
print a - b
print a * b


[4 5 6 7]
[ 4  6  8 10]
[-4 -4 -4 -4]
[ 0  5 12 21]

数学函数运算


In [3]:
print a * np.sin(b)
print a * np.sqrt(b)


[-0.         -0.95892427 -0.558831    1.9709598 ]
[ 0.          2.23606798  4.89897949  7.93725393]

从上面可以看出,对于常见的$+ \space - \space \times $都是每个元素之间的操作

矩阵积

矩阵乘法:$$C=A \times B$$

其中$A_{m \times n},B_{n \times p}$,那么矩阵$C_{m \times p}$,其中$$C_{ij}=\sum_{k=1}^{n}A_{ik}*B_{kj}$$


In [4]:
A = np.arange(0,9).reshape(3,3)
B = np.ones((3,3))
print A.dot(B)
print np.dot(A,B)


[[  3.   3.   3.]
 [ 12.  12.  12.]
 [ 21.  21.  21.]]
[[  3.   3.   3.]
 [ 12.  12.  12.]
 [ 21.  21.  21.]]

自增操作


In [5]:
a = np.arange(4)
print a
a +=1
print a
a -=2
print a


[0 1 2 3]
[1 2 3 4]
[-1  0  1  2]

通用函数

universal function 是对数组中的每个元素进行操作


In [6]:
a = np.arange(1,5)
print a
print np.sqrt(a)
print np.log(a)
print np.sin(a)


[1 2 3 4]
[ 1.          1.41421356  1.73205081  2.        ]
[ 0.          0.69314718  1.09861229  1.38629436]
[ 0.84147098  0.90929743  0.14112001 -0.7568025 ]

聚合函数

对数组进行操作,并返回一个数值


In [1]:
import numpy as np
a = np.array([3.3,4.5,5.7,0.3])
print a.sum()
print a.max()
print a.min()
print a.std()


13.8
5.7
0.3
2.00686322404

3 索引机制、切片和迭代方法

索引机制

通过方括号[]的索引机制 1 一维数组


In [2]:
a = np.arange(10,16)
print a
print a[1]
print a[-1]


[10 11 12 13 14 15]
11
15

方括号内传入多个参数,来获取多个值


In [3]:
print a[[1,3,4]]


[11 13 14]

2 二维数组


In [4]:
A = np.arange(10,19).reshape((3,3))
print A
print A[1,2]


[[10 11 12]
 [13 14 15]
 [16 17 18]]
15

切片操作

抽取数组中一部分形成一个新的数组,在Python列表中进行切片操作是原列表的副本,而在numpy中,则是原数据的一个缓冲。


In [5]:
a = range(5)
print a
a_a = a[1:3]
a_a[0]=10
print a_a
print a


[0, 1, 2, 3, 4]
[10, 2]
[0, 1, 2, 3, 4]

In [6]:
b = np.arange(10,16)
b_b1 = b[1:5]
print b_b1
b_b1[0]=20
print b_b1
print b


[11 12 13 14]
[20 12 13 14]
[10 20 12 13 14 15]

切片的语法:省略第一个元素,表示从0开始;省略第二元素,表示到最大的索引值;省略第三个元素表示间隔为1。 对于二维数组切片,不过要指定切片的维数。


In [7]:
A = np.arange(10,19).reshape((3,3))
print A
print A[0,:]
print A[0:2,0:2]


[[10 11 12]
 [13 14 15]
 [16 17 18]]
[10 11 12]
[[10 11]
 [13 14]]

对于不连续的索引,可以将这个索引放入一个数组中


In [8]:
print A[[0,2],0:2]


[[10 11]
 [16 17]]

数组迭代

在Python中可以通过for迭代的方式进行数据处理,在numpy中同样可以通过该方式


In [9]:
for row in A:
    print row


[10 11 12]
[13 14 15]
[16 17 18]

如果不想用多层迭代的方式遍历整个数组,可以用一下方式


In [10]:
for item in A.flat:
    print item,


10 11 12 13 14 15 16 17 18

当然numpy也支持其他当时来进行数组的迭代处理,apply_along_axis函数,该函数接受三个参数:聚合函数,对哪一轴数据处理和数组。


In [12]:
# axis=0 按列对数据进行处理
print np.apply_along_axis(np.mean,axis=0,arr=A)
# axis=1 按行对数据进行处理
print np.apply_along_axis(np.mean,axis=1,arr=A)


[ 13.  14.  15.]
[ 11.  14.  17.]

当然也可对自定义处理函数


In [13]:
def half(x):
    return x/2
print np.apply_along_axis(half,axis=0,arr=A)
print np.apply_along_axis(half,axis=1,arr=A)


[[5 5 6]
 [6 7 7]
 [8 8 9]]
[[5 5 6]
 [6 7 7]
 [8 8 9]]

4 条件和布尔数组

按照一定的条件从数组中筛选出一部分元素


In [14]:
A = np.random.random((4,4))
A


Out[14]:
array([[ 0.73400883,  0.60224597,  0.37735349,  0.5323983 ],
       [ 0.77960095,  0.96639406,  0.90195726,  0.67423709],
       [ 0.89192479,  0.08974329,  0.97089067,  0.83931719],
       [ 0.94710582,  0.20548919,  0.07497522,  0.98501641]])

In [15]:
A <0.5


Out[15]:
array([[False, False,  True, False],
       [False, False, False, False],
       [False,  True, False, False],
       [False,  True,  True, False]], dtype=bool)

In [16]:
# 按照条件抽选出数组
A[A<0.5]


Out[16]:
array([ 0.37735349,  0.08974329,  0.20548919,  0.07497522])

5 形状改变

reshape()函数改变数组的形状来形成一个新的数组


In [20]:
a = np.random.random(12)
print a
A = a.reshape((3,4))
print A
print a


[ 0.3978152   0.41831411  0.24663962  0.17015765  0.82213266  0.15743401
  0.69648778  0.41351352  0.77064567  0.34267312  0.64845064  0.99052632]
[[ 0.3978152   0.41831411  0.24663962  0.17015765]
 [ 0.82213266  0.15743401  0.69648778  0.41351352]
 [ 0.77064567  0.34267312  0.64845064  0.99052632]]
[ 0.3978152   0.41831411  0.24663962  0.17015765  0.82213266  0.15743401
  0.69648778  0.41351352  0.77064567  0.34267312  0.64845064  0.99052632]

不形成的数组,直接修改数组的shape属性


In [22]:
a.shape=(4,3)
a


Out[22]:
array([[ 0.3978152 ,  0.41831411,  0.24663962],
       [ 0.17015765,  0.82213266,  0.15743401],
       [ 0.69648778,  0.41351352,  0.77064567],
       [ 0.34267312,  0.64845064,  0.99052632]])

6 数组操作

连接数组

vstack()函数执行垂直入栈操作,数组朝垂直方向发展,hstack()函数执行水平方向入栈,数组朝水平方向发展。


In [25]:
A = np.ones((3,3))
B = np.zeros((3,3))
print np.vstack((A,B))
print np.hstack((A,B))


[[ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 0.  0.  0.]
 [ 0.  0.  0.]
 [ 0.  0.  0.]]
[[ 1.  1.  1.  0.  0.  0.]
 [ 1.  1.  1.  0.  0.  0.]
 [ 1.  1.  1.  0.  0.  0.]]

7 数组切分

数组切分是数组连接的逆操作,也分为hsplit()和vsplit()两种


In [26]:
A = np.arange(16).reshape((4,4))
print A
# 水平方向切割成两部分
B,C=np.hsplit(A,2)
print B
print C


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

In [27]:
B,C=np.vsplit(A,2)
print B
print C


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

split函数更为复杂,可以把数组分割成几个不对称的部分,还指定切分的索引,axis=0,表示为行索引,axis=1表示列索引


In [29]:
A1,A2,A3 = np.split(A,[1,3],axis=1)
print A1
print A2
print A3


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

In [30]:
A1,A2,A3 = np.split(A,[1,3],axis=0)
print A1
print A2
print A3


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

8 其他概念

副本和视图

numpy为所有的复制运算都不会为数组创建和数组的任何元素创建副本,如果想要创建副本,使用copy()函数


In [31]:
a = np.arange(4)
b = a
b[0]=10
a


Out[31]:
array([10,  1,  2,  3])

In [32]:
c = a[0:2]
c[0]=-1
a


Out[32]:
array([-1,  1,  2,  3])

In [33]:
d=a.copy()
d[0]=-10
a


Out[33]:
array([-1,  1,  2,  3])

广播机制

广播机制对两个及以上的数组进行运算或者是函数处理,满足的条件为:

  1. 连个数组的各维度的长度相同
  2. 如果不相容,其中那一维是1

In [34]:
A = np.arange(16).reshape((4,4))
B = np.arange(4)
print A
print B


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

数组A为$4 \times 4$而数组B为$4 \times 1$,但满足广播的条件


In [35]:
A+B


Out[35]:
array([[ 0,  2,  4,  6],
       [ 4,  6,  8, 10],
       [ 8, 10, 12, 14],
       [12, 14, 16, 18]])

9 结构化数组

数组的数据类型不仅可以说会用内置的,也可以自定义一些数据类型,记录一些事数据结构而不是独立的元素,指定dtype对象 bytes ---> b1

int ---> i1,i2,i4,i8

unsigned ints ---> u1,u2,u4,u8

floats ---> f2,f4,f8

complex ---> c8,c16

fix length strings ---> a


In [36]:
structured = np.array([(1,'first',0.5,1+2j),(2,'second',1.3,2-2j),(3,'third',0.8,1+3j)],dtype=('i2,a6,f4,c8'))
structured


Out[36]:
array([(1, 'first', 0.5, (1+2j)),
       (2, 'second', 1.2999999523162842, (2-2j)),
       (3, 'third', 0.800000011920929, (1+3j))], 
      dtype=[('f0', '<i2'), ('f1', 'S6'), ('f2', '<f4'), ('f3', '<c8')])

In [37]:
structured[0]


Out[37]:
(1, 'first', 0.5, (1+2j))

In [38]:
# 引用同列下
structured['f1']


Out[38]:
array(['first', 'second', 'third'], 
      dtype='|S6')

In [41]:
# 指定每一列的名称
structured = np.array([(1,'first',0.5,1+2j),(2,'second',1.3,2-2j),(3,'third',0.8,1+3j)],dtype=[('id','i2'),('position','a6'),('value','f4'),('complex','c8')])
structured


Out[41]:
array([(1, 'first', 0.5, (1+2j)),
       (2, 'second', 1.2999999523162842, (2-2j)),
       (3, 'third', 0.800000011920929, (1+3j))], 
      dtype=[('id', '<i2'), ('position', 'S6'), ('value', '<f4'), ('complex', '<c8')])

In [42]:
structured.dtype.names=('id','order','value','complex')
structured['order']


Out[42]:
array(['first', 'second', 'third'], 
      dtype='|S6')

数组文件的读写

二进制文件读写


In [43]:
data = np.random.random((4,4))
data


Out[43]:
array([[ 0.2221668 ,  0.9706598 ,  0.54925123,  0.64682071],
       [ 0.12963963,  0.46067035,  0.06317391,  0.58332403],
       [ 0.01289828,  0.0865052 ,  0.78685014,  0.41963821],
       [ 0.79213621,  0.48485406,  0.06690978,  0.56216146]])

In [44]:
np.save('saved_data',data)

In [45]:
loaded_data=np.load('saved_data.npy')
loaded_data


Out[45]:
array([[ 0.2221668 ,  0.9706598 ,  0.54925123,  0.64682071],
       [ 0.12963963,  0.46067035,  0.06317391,  0.58332403],
       [ 0.01289828,  0.0865052 ,  0.78685014,  0.41963821],
       [ 0.79213621,  0.48485406,  0.06690978,  0.56216146]])

csv 文件读写

data.csv

id,value1,value2,value3

1,123,1.4,23

2,110,0.5,18

3,164,2.1,19


In [1]:
import numpy as np
data = np.genfromtxt('data.csv',delimiter=',',names=True)
data


Out[1]:
array([(1.0, 123.0, 1.4, 23.0), (2.0, 110.0, 0.5, 18.0),
       (3.0, 164.0, 2.1, 19.0)], 
      dtype=[('id', '<f8'), ('value1', '<f8'), ('value2', '<f8'), ('value3', '<f8')])

In [2]:
data['id']


Out[2]:
array([ 1.,  2.,  3.])

In [ ]: