《Python数据分析基础教程,munpy学习指南(第二版)》:代码
http://www.pudn.com/Download/item/id/2742220.html
numpy 学习指南
http://www.pudn.com/Download/item/id/2742220.html
https://www.jianshu.com/p/04d180d90a3f
https://wizardforcel.gitbooks.io/pandas-cookbook-code-notes/content/2.html
1,测试numpy 和python 自带数组操作时间比较
import numpy as np
import datetime as datetime
def numpysum(n):
a = np.arange(n) ** 2
b = np.arange(n) ** 3
c = a + b
return c
def pythonsum(n):
a = list(range(n))
b = list(range(n))
c = []
for i in range(len(a)):
a[i] = i ** 2
b[i] = i ** 3
c.append(a[i] + b[i])
return c
start = int(round(time.time() * 1000))
c = numpysum(500000)
delta = int(round(time.time() * 1000)) - start
print("numpysum use " )
print(str(delta))
start = int(round(time.time() * 1000))
c = pythonsum(500000)
delta = int(round(time.time() * 1000)) - start
print("pysum use " )
print(str(delta))
帮助
np.arange?
NumPy 数组对象
ndarray是一个多维数组对象,该对象由两部分组成, (The N-dimensional array (ndarray
))
实际的数据;
描述这些数据的元数据
大部分的数组操作仅仅修改元数据部分,而不改变底层的实际数据
一维数组向量:
一个包含5个元素的向量,取值分别为0~4的整数。数组的shape属性返回一个元组(tuple),元组中的元素即为NumPy数组每一个维度上的大小
a = np.arange(5)
print(a)
a.dtype
[0 1 2 3 4]
dtype('int64')
a.shape
(5,)
多维数据向量
m = np.array([np.arange(2), np.arange(2)])
m.shape 2
[[0 1]
[0 1]]
##3x3维度
np.array([np.arange(3), np.arange(3), np.arange(3)])
选取数组
a[m,n] m,n 为元素下标
[0,0][0,1]
[1,0][1,1]
numpy 数据类型
bool 用一位存储的布尔类型(值为TRUE或FALSE)
inti 由所在平台决定其精度的整数(一般为int32或int64)
int8 整数,范围为128至127
int16 整数,范围为32 768至32 767
int32 整数,范围为231至231 1
int64 整数,范围为263至263 1
uint8 无符号整数,范围为0至255
uint16 无符号整数,范围为0至65 535
uint32 无符号整数,范围为0至2321
uint64 无符号整数,范围为0至2641
float16 半精度浮点数(16位):其中用1位表示正负号,5位表示指数,10位表示尾数
float32 单精度浮点数(32位):其中用1位表示正负号,8位表示指数,23位表示尾数
float64或float 双精度浮点数(64位):其中用1位表示正负号,11位表示指数,52位表示尾数
complex64 复数,分别用两个32位浮点数表示实部和虚部
complex128或complex 复数,分别用两个64位浮点数表示实部和虚部
数据类型对象:
数据类型对象是numpy.dtype类的实例。如前所述,NumPy数组是有数据类型的,更确切地说,NumPy数组中的每一个元素均为相同的数据类型。数据类型对象可以给出单个数组元素在内存中占用的字节数,即dtype类的itemsize属性. m.dtype.itemsize
字符编码
整数 i
无符号整数 u
单精度浮点数 f
双精度浮点数 d
布尔值 b
复数 D
字符串 S
unicode字符串 U
void (空) V
np.arange(7, dtype='f')
自定义数据类型
In: dtype(float)
Out: dtype('float64')
In: dtype('f')
Out: dtype('float32')
In: dtype('d')
Out: dtype('float64')
创建自定义数据类型
t = np.dtype([('name',str, 40), ('numitems', int), ('price',float)])
t['name']
itemz = np.array([('Meaning of life DVD', 42, 3.14), ('Butter', 13, 2.72)], dtype=t)
t = np.dtype([('name', 'S', 40), ('numitems', 'int32'), ('price', 'float32')]) ##这个是正常的
获取帮助 np.dtype?
一维数组的索引和切片
In: a[::-1]
Out: array([8, 7, 6, 5, 4, 3, 2, 1, 0]) 利用负数下标翻转数组
多维数组的切片和索引
b = np.arange(24).reshape(2,3,4)
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
b.shape
(2, 3, 4)
多维数组b中有0~23的整数,共24个元素,是一个2×3×4的三维数组。我们可以形象地把它看做一个两层楼建筑,每层楼有12个房间,并排列成3行4列
或者将其看成是电子表格中工作表(sheet)、行和列的关系
#以用三维坐标来选定任意一个房间,即楼层、行号和列号
b[0,0,0]
#如果我们不关心楼层,也就是说要选取所有楼层的第1行、第1列的房间,那么可以将第1个下标用英文标点的冒号:来代替
b[:, 0,0]
#选取第1层楼的所有房间
b[0, :, :]
多个冒号可以用一个省略号(...)来代替
b[0, ...]
#选取第1层楼、第2排的所有房间
b[0,1]
#数组切片中间隔地选定元素
b[0,1,::2]
#要选取所有楼层的位于第2列的房间,即不指定楼层和行号
b[...,1]
#选取所有位于第2行的房间,而不指定楼层和列号
b[:,1]
#选取第1层楼的所有位于第2列的房间
b[0,:,1]
#要选取第1层楼的最后一列的所有房间
b[0,::-1, -1]
#该数组切片中间隔地选定元素
b[0,::2,-1]
#数组切片中间隔地选定元素
b[0,::2,-1]
#第1层楼和第2层楼的房间交换
b[::-1]
改变数组的维度
#用ravel函数完成展平的操作
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
b.ravel()
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23])
#flatten就是展平的意思,与ravel函数的功能相同,flatten函数会请求分配内存来保存结果,而ravel函数只是返回数组的一个视图(view)
b.flatten()
#用元组设置维度
b.shape = (6,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])
# transpose 在线性代数中,转置矩阵是很常见的操作。对于多维数组
b.transpose()
array([[ 0, 4, 8, 12, 16, 20],
[ 1, 5, 9, 13, 17, 21],
[ 2, 6, 10, 14, 18, 22],
[ 3, 7, 11, 15, 19, 23]])
# resize resize和reshape函数的功能一样,但resize会直接修改所操作的数组
b.resize((2,12))
组合数组
水平组合,垂直, 深度组合,列组合,行组合
import numpy as np
a = np.arange(9).reshape(3,3)
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
b = 2 * a
array([[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]])
## 水平组合
np.hstack((a,b))
np.concatenate((a,b), axis=1)
array([[ 0, 1, 2, 0, 2, 4],
[ 3, 4, 5, 6, 8, 10],
[ 6, 7, 8, 12, 14, 16]])
##垂直
np.vstack((a,b))
np.concatenate((a, b), axis = 0)
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]])
#深度组合 是将一系列数组沿着纵轴(深度)方向进行层叠组合
举个例子,有若干张二维平面内的图像点阵数据,我们可以将这些图像数据沿纵轴方向层叠在一起
np.dstack((a,b))
array([[[ 0, 0],
[ 1, 2],
[ 2, 4]],
[[ 3, 6],
[ 4, 8],
[ 5, 10]],
[[ 6, 12],
[ 7, 14],
[ 8, 16]]])
##列组合 column_stack函数对于一维数组将按列方向进行组合
In: oned = arange(2)
In: oned
Out: array([0, 1])
In: twice_oned = 2 * oned
In: twice_oned
Out: array([0, 2])
In: column_stack((oned, twice_oned))
Out:
array([[0, 0],
[1, 2]])
对于二维数组,column_stack与hstack的效果是相同的
In: column_stack((a, b))
Out:
array([[ 0, 1, 2, 0, 2, 4],
[ 3, 4, 5, 6, 8,10],
[ 6, 7, 8,12,14,16]])
In: column_stack((a, b)) == hstack((a, b))
Out:
array([[ True, True, True, True, True, True],
[ True, True, True, True, True, True],
[ True, True, True, True, True, True]], dtype=bool)
我们可以用==运算符来比较两个NumPy数组
#行组合
In: row_stack((oned, twice_oned))
Out:
array([[0, 1],
[0, 2]])
对于二维数组,row_stack与vstack的效果是相同的:
In: row_stack((a, b))
Out:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 0, 2, 4],
[ 6, 8,10],
[12,14,16]])
In: row_stack((a,b)) == vstack((a, b))
Out:
array([[ True, True, True],
[ True, True, True],
[ True, True, True],
[ True, True, True],
[ True, True, True],
[ True, True, True]], dtype=bool)
数组的分割
NumPy数组可以进行水平、垂直或深度分割,相关的函数有hsplit、vsplit、dsplit和split。我们可以将数组分割成相同大小的子数组,也可以指定原数组中需要分割的位置
##水平分割 把数组沿着水平方向分割为3个相同大小的子数组:
hsplit(a, 3)
##垂直分割
##深度分割
##
数组的属性
除了shape和dtype属性以外,ndarray对象还有很多其他的属
nidm
b.ndim 维度
size属性 给出数组元素的总个数
itemsize属性,给出数组中的元素在内存中所占的字节数
使用tolist函数将NumPy数组转换成Python列表
In: b
Out: array([ 1.+1.j, 3.+2.j])
In: b.tolist()
Out: [(1+1j), (3+2j)]
astype函数可以在转换数组时指定数据类型
In: b
Out: array([ 1.+1.j, 3.+2.j])
In: b.astype(int)
/usr/local/bin/ipython:1: ComplexWarning: Casting complex values to real discards the
imaginary part
#!/usr/bin/python
Out: array([1, 3])
股票实验
原始数据
AAPL,28-01-2011, ,344.17,344.4,333.53,336.1,21144800
AAPL,31-01-2011, ,335.8,340.04,334.3,339.32,13473000
AAPL,01-02-2011, ,341.3,345.65,340.98,345.03,15236800
AAPL,02-02-2011, ,344.45,345.25,343.55,344.32,9242600
AAPL,03-02-2011, ,343.8,344.24,338.55,343.44,14064100
AAPL,04-02-2011, ,343.61,346.7,343.51,346.5,11494200
AAPL,07-02-2011, ,347.89,353.25,347.64,351.88,17322100
AAPL,08-02-2011, ,353.68,355.52,352.15,355.2,13608500
AAPL,09-02-2011, ,355.19,359,354.87,358.16,17240800
AAPL,10-02-2011, ,357.39,360,348,354.54,33162400
AAPL,11-02-2011, ,354.75,357.8,353.54,356.85,13127500
AAPL,14-02-2011, ,356.79,359.48,356.71,359.18,11086200
AAPL,15-02-2011, ,359.19,359.97,357.55,359.9,10149000
AAPL,16-02-2011, ,360.8,364.9,360.5,363.13,17184100
AAPL,17-02-2011, ,357.1,360.27,356.52,358.3,18949000
AAPL,18-02-2011, ,358.21,359.5,349.52,350.56,29144500
AAPL,22-02-2011, ,342.05,345.4,337.72,338.61,31162200
AAPL,23-02-2011, ,338.77,344.64,338.61,342.62,23994700
AAPL,24-02-2011, ,344.02,345.15,338.37,342.88,17853500
AAPL,25-02-2011, ,345.29,348.43,344.8,348.16,13572000
AAPL,28-02-2011, ,351.21,355.05,351.12,353.21,14395400
AAPL,01-03-2011, ,355.47,355.72,347.68,349.31,16290300
AAPL,02-03-2011, ,349.96,354.35,348.4,352.12,21521000
AAPL,03-03-2011, ,357.2,359.79,355.92,359.56,17885200
AAPL,04-03-2011, ,360.07,360.29,357.75,360,16188000
AAPL,07-03-2011, ,361.11,361.67,351.31,355.36,19504300
AAPL,08-03-2011, ,354.91,357.4,352.25,355.76,12718000
AAPL,09-03-2011, ,354.69,354.76,350.6,352.47,16192700
AAPL,10-03-2011, ,349.69,349.77,344.9,346.67,18138800
AAPL,11-03-2011, ,345.4,352.32,345,351.99,16824200
分析日期数据
from datetime import datetime
def datestr2num(s):
return datetime.strptime(s.decode("utf-8"), "%d-%m-%Y").date().weekday()
dates, close=np.loadtxt('data.csv', delimiter=',', converters={1: datestr2num}, usecols=(1,6), unpack=True)
dates
array([4., 0., 1., 2., 3., 4., 0., 1., 2., 3., 4., 0., 1., 2., 3., 4., 1.,
2., 3., 4., 0., 1., 2., 3., 4., 0., 1., 2., 3., 4.])
averages = np.zeros(5)
for i in range(5):
indices = np.where(dates == i)
prices = np.take(close, indices)
avg = np.mean(prices)
print("Day", i, "prices", prices, "Average", avg )
averages[i] = avg
np.max(averages) argmax函数返回的是averages数组中最大元素的索引值
NumPy的ndarray:一种多维数组对象
In [12]: import numpy as np
# Generate some random data
In [13]: data = np.random.randn(2, 3)
In [14]: data
Out[14]:
array([[-0.2047, 0.4789, -0.5194],
[-0.5557, 1.9658, 1.3934]])
In [15]: data * 10
Out[15]:
array([[ -2.0471, 4.7894, -5.1944],
[ -5.5573, 19.6578, 13.9341]])
In [16]: data + data
Out[16]:
array([[-0.4094, 0.9579, -1.0389],
[-1.1115, 3.9316, 2.7868]])
#元素自身想运算
ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有一个shape(一个表示各维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象)
创建ndarray
In [19]: data1 = [6, 7.5, 8, 0, 1]
In [20]: arr1 = np.array(data1)
In [21]: arr1
Out[21]: array([ 6. , 7.5, 8. , 0. , 1. ])
##或
In [22]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
In [23]: arr2 = np.array(data2)
除np.array之外,还有一些函数也可以新建数组。比如,zeros和ones分别可以创建指定长度或形状的全0或全1数组。empty可以创建一个没有任何具体值的数组。要用这些方法创建多维数组,只需传入一个表示形状的元组即可:
In [29]: np.zeros(10)
Out[29]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [30]: np.zeros((3, 6))
Out[30]:
array([[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.]])
In [31]: np.empty((2, 3, 2))
Out[31]:
array([[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]])
arange是Python内置函数range的数组版:
ndarray的数据类型
In [33]: arr1 = np.array([1, 2, 3], dtype=np.float64)
In [34]: arr2 = np.array([1, 2, 3], dtype=np.int32)
In [35]: arr1.dtype
Out[35]: dtype('float64')
In [36]: arr2.dtype
Out[36]: dtype('int32')
数据类型转化
In [37]: arr = np.array([1, 2, 3, 4, 5])
In [38]: arr.dtype
Out[38]: dtype('int64')
In [39]: float_arr = arr.astype(np.float64)
In [40]: float_arr.dtype
Out[40]: dtype('float64')
如果将浮点数转换成整数,则小数部分将会被截取删除
如果某字符串数组表示的全是数字,也可以用astype将其转换为数值形式:
In [44]: numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
In [45]: numeric_strings.astype(float)
Out[45]: array([ 1.25, -9.6 , 42. ])
注意:使用numpy.string_类型时,一定要小心,因为NumPy的字符串数据是大小固定的,发生截取时,不会发出警告。pandas提供了更多非数值数据的便利的处理方法。
NumPy数组的运算
不用编写循环即可对数据执行批量运算。NumPy用户称其为矢量化(vectorization)。大小相等的数组之间的任何算术运算都会将运算应用到元素级
In [51]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])
In [52]: arr
Out[52]:
array([[ 1., 2., 3.],
[ 4., 5., 6.]])
In [53]: arr * arr
Out[53]:
array([[ 1., 4., 9.],
[ 16., 25., 36.]])
In [54]: arr - arr
Out[54]:
array([[ 0., 0., 0.],
[ 0., 0., 0.]])
数组与标量的算术运算会将标量值传播到各个元素: 计算动作会在每一个元素上执行
大小相同的数组之间的比较会生成布尔值数组:
不同大小的数组之间的运算叫做广播(broadcasting)
In [57]: arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
In [58]: arr2
Out[58]:
array([[ 0., 4., 1.],
[ 7., 2., 12.]])
In [59]: arr2 > arr
Out[59]:
array([[False, True, False],
[ True, False, True]], dtype=bool)
基本的索引和切片
当你将一个标量值赋值给一个切片时(如arr[5:8]=12),该值会自动传播(也就说后面将会讲到的“广播”)到整个选区。跟列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上。
即: 对切片的操作会反应到源数据上,类似数据映射的关系
注意:如果你想要得到的是ndarray切片的一份副本而非视图,就需要明确地进行复制操作,例如arr[5:8].copy()
在多维数组中,如果省略了后面的索引,则返回对象会是一个维度低一点的ndarray(它含有高一级维度上的所有数据)
In [76]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
arr3d[0] #一个2×3数组
切片索引
二维数组arr2d:沿着第0轴(即第一个轴)切片的。也就是说,切片是沿着一个轴向选取元素的。表达式arr2d[:2]可以被认为是“选取arr2d的前两行”
In [90]: arr2d
Out[90]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [91]: arr2d[:2]
Out[91]:
array([[1, 2, 3],
[4, 5, 6]])
注意,“只有冒号”表示选取整个轴
In [95]: arr2d[:, :1]
Out[95]:
array([[1],
[4],
[7]])
布尔型索引
In [98]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
In [99]: data = np.random.randn(7, 4)
In [100]: names
Out[100]:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'],
dtype='<U4')
In [101]: data
Out[101]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.0072, -1.2962, 0.275 , 0.2289],
[ 1.3529, 0.8864, -2.0016, -0.3718],
[ 1.669 , -0.4386, -0.5397, 0.477 ],
[ 3.2489, -1.0212, -0.5771, 0.1241],
[ 0.3026, 0.5238, 0.0009, 1.3438],
[-0.7135, -0.8312, -2.3702, -1.8608]])
In [102]: names == 'Bob'
Out[102]: array([ True, False, False, True, False, False, False], dtype=bool)
In [103]: data[names == 'Bob']
Out[103]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.669 , -0.4386, -0.5397, 0.477 ]])
布尔型数组的长度必须跟被索引的轴长度一致。此外,还可以将布尔型数组跟切片、整数(或整数序列,稍后将对此进行详细讲解)混合使用:
In [103]: data[names == 'Bob']
Out[103]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.669 , -0.4386, -0.5397, 0.477 ]])
In [104]: data[names == 'Bob', 2:]
Out[104]:
array([[ 0.769 , 1.2464],
[-0.5397, 0.477 ]])
In [105]: data[names == 'Bob', 3]
Out[105]: array([ 1.2464, 0.477 ])
要选择除"Bob"以外的其他值,既可以使用不等于符号(!=),也可以通过~对条件进行否定:
data[~(names == 'Bob')]
##或
cond = names == 'Bob'
data[~cond]
选取这三个名字中的两个需要组合应用多个布尔条件,使用&(和)、|(或)之类的布尔算术运算符即可
mask = (names == 'Bob') | (names == 'Will')
通过布尔型索引选取数组中的数据,将总是创建数据的副本,即使返回一模一样的数组也是如此。
通过布尔型数组设置值是一种经常用到的手段。为了将data中的所有负值都设置为0,我们只需
data[data < 0] = 0
通过一维布尔数组设置整行或列的值也很简单:
data[names != 'Joe'] = 7
花式索引
花式索引(Fancy indexing)是一个NumPy术语,它指的是利用整数数组进行索引。假设我们有一个8×4数组: