[开源库学习] Numpy日记 Section.2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sc_lilei/article/details/80683071

前言

   最近开始学习Data anaysis,将numpy入门学习日记分享出来,也当做个记录。

 【Numpy官网学习地址】:Click Here

   备注:

        我尽可能的将官网快速教程中的case都贴出来了,但越往下越发现这个库是真的庞大,教程也是由浅及深,后面会涉及到向量、线性代数等高数概念,这个日记中不会提到,需要的话自行前往官网查看。这个日记分为两个Section,加起来可能占到官网快速教程中的case的80%左右,入门Numpy足矣。

    Numpy日记 Section.1

正文


#broadcast 机制
#一般来说,只有相同shape的ndarray对象才能进行算术运算,如下
a23 = np.array(range(3)) #[0  1  2]
a23_t = np.ones(3) # [1. 1. 1.]
#print(a23+a23_t)  # [1. 2. 3.]
#上面的需求很简单,把一个数组对象的所有元素都加1,看不出什么问题,如果现在要让所有元素都*3
# 难道要创建一个np.array([3,3,3]),再去乘以a23吗?当然不太科学,可以这样实现
print(a23*3)  #同a23 * [3]
#这就是broadcast机制,numpy处理两个形状不同的数组时,会将长度/维度较小的数组按照较大的
# 数组的尺寸进行“广播”(可理解为扩张),这个例子中,[3] “广播”成 [3,3,3],这是numpy的处理方法,但实际执行时
# 并不会真正的对数组元素进行复制,所以执行效率高
a23_t1 = np.ones((2,3,4)) #三维数组,3行4列
a23_t2 = np.ones((3,1)) #二维数组,3行1列
a23_t3 = np.ones(3) #[1. 1. 1.]
a23_t4 = np.ones(4) #[1. 1. 1. 1.]

# print(a23_t2+a23_t1,111) #OK
# print(a23_t3+a23_t1,222) #抛异常,无法按照a23_t1的尺寸对a23_t3进行广播
# print(a23_t4+a23_t1,333)  #OK
#广播操作也有原则,不同维数(至少是一维,单个元素不算是一维数组)数组间的进行算术运算时,他们的列数必须相等,
# 也就是shape的最后一个值必须相等,否则无法进行运算
# 例外:单列多行的数组(二维)可以与单行多列的数组(一维)之间可以进行运算
a23_t5 = np.ones((2,1,4))
print(a23_t1+a23_t5,444)
a23_t6 = np.ones((2,3,3))
#print(a23_t1+a23_t6,555)  #抛出异常

#几个例子
t = np.arange(4) # shape = (4,) 单行4列
t1 = t.reshape(4,1) # shape = (4,1) 单列4行
v = np.ones(5) #shape = (5,) 单行5列
v1 = np.ones((3,4))  #shape = (3,4) 3行4列

#tv = t + v  # ERROR
t1v = t1 + v  #OK 印证上面提到的例外
tv1 = t + v1 #OK



#shape 变换
a24 = np.floor(10*np.random.random((3,4)))
#print(a24.shape)  #(3,4)
a24_flat = a24.ravel()  #无论几维,均转换为一维,等效于reshape(1,12)
#print(a24_flat) #[7. 9. 5. 3. 3. 1. 7. 5. 2. 1. 1. 0.]
#print(a24.reshape(6,2)) #打印临时修改shape后的数组,并不会修改原数组的shape
print(a24)
print(a24.T)  #将多维数组进行顺时针旋转90度(看起来像是这样),shape参数对调

a24.resize((6,2)) #直接修改原数组对象
print(a24)

print(a24.reshape(3,-1))  #若只想传入一个尺寸参数,另一个自动计算,就可以用-1填充另一个参数的位置。



#ndarray对象的堆叠操作
# https://docs.scipy.org/doc/numpy/user/quickstart.html#stacking-together-different-arrays
a25 = np.ceil(10*np.random.random((2,2)))
print(a25)
a25_t = np.ceil(10*np.random.random((2,2)))
print(a25_t)
vertically_stacked = np.vstack((a25,a25_t))  #垂直堆叠
horizontally_stacked = np.hstack((a25,a25_t)) #水平堆叠

#column_stack方法: 水平堆叠二维数组,或将一维数组垂直堆叠后再self.transpose()得到一个二维数组
print(np.column_stack((a25,a25_t)))
a25_t1 = np.array([1,0,2])
a25_t2 = np.array([2,3,1])
# print(np.column_stack((a25_t1,a25_t2)))
# print(np.vstack((a25_t1,a25_t2)).T)  #column_stack操作一维数组时等效于此操作


#ndarray对象的分割操作:
# https://docs.scipy.org/doc/numpy/reference/generated/numpy.array_split.html#numpy.array_split
a26 = np.arange(8)
a26_t = np.array([ [1,23,2], [3,4,1], [2,2,2] ])
a26_vsplit = np.array_split(a26,3,axis=0) #[array([0, 1, 2]), array([3, 4, 5]), array([6, 7])]
a26_t_vsplit = np.array_split(a26_t,3,axis=0) # [array([[ 1, 23,  2]]), array([[3, 4, 1]]), array([[2, 2, 2]])]


#拷贝和视图
# https://docs.scipy.org/doc/numpy/user/quickstart.html#copies-and-views
a27 = np.arange(12)
a27_t = a27   #这种操作不会创建新对象(不拷贝),两个变量指向同一个对象
#但是修改任意一个变量会导致另一个变量也改变
print(a27 is a27_t)  #True
a27.resize((2,6))
print(a27.shape, a27_t.shape)  #(2, 6) (2, 6)

a27_t1 = a27.view() #视图(浅拷贝):这个方法创建了新的对象,但两个对象共享一份数据,其他属性不相关
#创建了新的对象,意味着两者互不相关
print(a27_t1 is a27, a27_t1.base is a27) #False, True
a27_t1.resize((3,4))
print(a27.shape, a27_t1.shape) #(2, 6) (3, 4)
a27[:] = 0
print(a27.ravel() == a27_t1.ravel()) #[True True ...(all True) ] 改变原对象的数据,新对象的数据也跟着改变了


a27_t2 = a27[:,:2] #分片操作不会创建新对象
a27_t2[:] = 666
print(a27)

a27_t3 = a27.copy() #深拷贝,完全创建一个新对象,与原对象毫不相关
print(a27_t3 is a27, a27_t3.base is a27) #False, False
a27[:] = 0
print(a27 == a27_t3)  #[(false)...]
a27_t3.resize((1,12))
print(a27.shape == a27_t3.shape)  #False



#结构化数组:它也是ndarray对象,但其datatype是由命名字段的序列组合构成的,这是原文直译,需要结合实例理解
# https://docs.scipy.org/doc/numpy/user/basics.rec.html#structured-arrays

datatype = [('name','U10'), ('age','i4'), ('weight','f4')]
a28 = np.array([('eli',22,101.0), ('alex',30,140.5)], dtype=datatype)
print(a28, a28.dtype) #[('eli', 22, 101. ) ('alex', 30, 140.5)] \
# [('name', '<U10'), ('age', '<i4'), ('weight', '<f4')]
#这里的a28是一个一维数组,它的datatype是由三个字段组成的结构化组合。
# U10:长度<=10的string,字段名为name; i4: 4字节的整数,字段名为age; f4: 4字节的浮点数,字段名为weight

print(a28[1])  #('alex', 30, 140.5)  索引正常使用
print(a28['name'])  #['eli' 'alex']     使用字段进行索引
a28['age'] = '66'  #利用索引修改数据
print(a28)  #[('eli', 66, 101. ) ('alex', 66, 140.5)]

#dtype可以使用np.dtype函数构造,它是由一系列元组组合成的list,一个字段名占一个元组
# 一个元组有三个参数(fieldname, datatype, shape),shape可选,shape可以是单独一个元组
dtype = np.dtype([('name','S5'),('age', np.int32), ('weight', np.float32), ('location', 'f4', (2,))])
a28_t = np.array( [('lei',22,123.5,(3,4)), ('amor',25,140.1,(5,7))] ,dtype=dtype)
print(a28_t) #[(b'lei', 22, 123.5, [3., 4.]) (b'amor', 25, 140.1, [5., 7.])]

#快速创建dtype,字段名会以'f#'的形式自动创建
dtype1 = np.dtype('i4,f4,S3')
print(dtype1)  #[('f0', '<i4'), ('f1', '<f4'), ('f2', '<U3')]
dtype2 = np.dtype('3int8, float32, (2,3)float64')
print(dtype2) #[('f0', 'i1', (3,)), ('f1', '<f4'), ('f2', '<f8', (2, 3))]
哪儿不对或者有疑问,各位老铁可以留言,我会尽量回复。

猜你喜欢

转载自blog.csdn.net/sc_lilei/article/details/80683071