《python for data analysis》第四章,numpy的基本使用

时间:2023-12-10 17:58:14

《利用python进行数据分析》第四章的程序,介绍了numpy的基本使用方法。(第三章为Ipython的基本使用)

科学计算、常用函数、数组处理、线性代数运算、随机模块……

# -*- coding:utf-8 -*-
# 《python for data analysis》第四章, numpy基础
# 数组与矢量计算
import numpy as np
import time # 开始计时
start = time.time() # 创建一个array
data = np.array([[1, 2, 3, 4, 5, 6],
[7, 8, 9, 10, 11, 12]], dtype=np.int32) # 输入类型为tuple时效果一致, 可指定数据类型,也可缺省
print('data:'),
print(data)
print('data.shape:'),
print(data.shape) # 等价于np.shape(data),(2L,6L),tuple型
print('data.dtype:'),
print(data.dtype) # 显示元素的变量类型,int32
print('type(data):'),
print(type(data)) # 显示整个array的变量类型,numpy.ndarray
print('↑---------------------class1\n\n') # 快速创建一些特殊格式的array
print(np.ones(shape=(2, 3))) # 打印一个2*3,元素全为1的矩阵
print(np.zeros(shape=(3, 2))) # 打印一个3*2,元素全为0的矩阵
print(np.empty(shape=(3, 5))) # 打印一个3*5,元素随机的矩阵
print(np.arange(0, 3)) # np.arange同python内置的range,range()产生list对象,np.arange产生array对象。 result: array([0,1,2])
print(np.eye(5)) # 创建一个五阶单位矩阵, 等同于np.identity(5)
print('↑---------------------class2\n\n') # ndarray的数据类型
# 用.astype()进行数据类型转换,int转float, 注意float转int时会截尾
print(data.dtype)
data = data.astype(np.float64)
print(data.dtype)
# string转float
data = np.array(['1.23', '2.34', '3.45'])
data = data.astype(np.float64)
print(data)
print(data.dtype)
print('↑---------------------class3\n\n') # 数组与数组、数组与标量之间的运算
# 1、数组与标量运算,将标量值按照相同的运算规则传播到数组内的各个元素
data = np.arange(1, 6)
print('data:'),
print(data)
data = data + 2
print('data+2:'),
print(data)
# 2、数组与数组运算,且两个数组的shape相同,此时任何算术运算均会应用到元素级
data1 = np.arange(1, 6)
data2 = np.ones(5).astype(np.int32)
print('\ndata1:'),
print(data1)
print('data2:'),
print(data2)
print('data1 * data2:'),
print(data1 * data2)
print('data1 + data2:'),
print(data1 + data2)
# 3、数组与数组运算,且两个数组的shape不相同,此时启用numpy的广播(broadcast)机制
# http://baijiahao.baidu.com/s?id=1580719686756248184&wfr=spider&for=pc 广播机制用图说明过程
data1 = np.arange(1, 6).reshape(-1, 1)
data2 = np.arange(1, 6)
print('\ndata1:'),
print(data1)
print('data2:'),
print(data2)
print('data1 + data2:'),
print(data1 + data2)
print('↑---------------------class4\n\n') # 基本的索引与切片
# 创建一个切片
data = np.arange(1, 10)
slice_data = data[2:5] # slice_data是data的一个切片
# ★★★★★array的切片是原array的一个视图(引用),切片上任何数据的修改都会直接反映到原array上
print(data) # [1 2 3 4 5 6 7 8 9]
print(slice_data) # [3 4 5]
slice_data[1] = 100
print(slice_data) # [ 3 100 5]
print(data) # [ 1 2 3 100 5 6 7 8 9]
# 这和list的切片规则是完全不一样的,list的切片是原list的一个复制
origin_list = range(1, 10)
slice_list = origin_list[2:5]
print(origin_list) # [1 2 3 4 5 6 7 8 9]
print(slice_list) # [3 4 5]
slice_list[1] = 100
print(slice_list) # [ 3 100 5]
print(origin_list) # [1 2 3 4 5 6 7 8 9]
# array的切片通过.copy()也可以像list那样复制数据而不是引用
data = np.arange(1, 10)
slice_data = data[2:5].copy() # slice_data是data的一个切片,复制,而不是引用
print(data) # [1 2 3 4 5 6 7 8 9]
print(slice_data) # [3 4 5]
slice_data[1] = 100
print(slice_data) # [ 3 100 5]
print(data) # [1 2 3 4 5 6 7 8 9]
# 一维数组的索引直接写入标量实现
# 二维及以上数组的索引是一个一维数组,行向量与列向量写法等价
data_2d = np.empty(shape=(3, 3))
print(data_2d[1, 2] == data_2d[1][2])
print('↑---------------------class5\n\n') # 索引方式,3种
# 1、切片索引,切片为原数组的视图,数据引用
data = np.arange(1, 6) # array([1,2,3,4,5])
data_slice = data[1:3] # array([2,3]),
print(data_slice)
data_nd = np.arange(1, 10).reshape(3, 3) # 高维数组的切片索引还可以结合整数索引混合使用
data_slice = data_nd[1, 1:] # array([5,6])
print(data_slice)
data_slice = data_nd[2, :] # array([7,8,9]) , : 表示选取整条轴
print(data_slice)
print(' ')
# 2、布尔型索引,切片为数据复制
name = np.array(['a', 'b', 'a', 'b', 'c', 'd'])
data = np.arange(1, 19).reshape(6, 3)
data_slice = data[name == 'a']
print(data)
print(data_slice)
data_slice[1] = 1 # 布尔型索引产生的子集是数据的复制而不是视图,对子集的改变不影响原数组
print(data)
print(data_slice)
data[data > 10] = 10
print(data)
data[(data == 2) | (data == 7)] = 1
print(data)
print('')
# 3、花式索引(fancy indexing),用整数数组进行索引
data = np.arange(1, 10).reshape(3, 3)
data_slice = data[[1, 2, 0]]
print(data)
print(data_slice)
data_slice[1] = 1 # 花式索引产生的子集也是数据的复制
print(data)
print(data_slice)
data_slice = data[[0, 1]][:, [0, 1]] # 花式索引还可以选中原数组的某个矩形区域,也可以写为data[np.ix_([0,1],[0,1]])]
print(data_slice)
print('↑---------------------class6\n\n') # 数据转置与轴对换
data = np.arange(1, 10).reshape(3, 3)
print(data)
data_T = data.T # 转置,也可以写为 data = data.transpose()
print(data_T)
data_T[1] = 1 # 转置返回的是原数组的视图,无数据的复制
print(data_T)
print(data)
print('↑---------------------class7\n\n') # 通用函数,对数组使用,并对其中的数据执行元素级的函数运算
# abs\square\sqrt\sign\ceil\floor\rint\mod\exp等等
data = np.arange(10)
data2 = np.sqrt(data)
print(data)
print(data2)
print('↑---------------------class8\n\n') # 条件逻辑的数组运算,用np.where来替代x if condition else y
a = np.array([1, 2, 3, 4, 5])
b = np.array([6, 7, 8, 9, 0])
condition = np.array([True, False, True, True, False])
result1 = [(a if condition else b) for a, b, condition in zip(a, b, condition)]
print(result1)
a = np.array([1, 2, 3, 4, 5])
b = np.array([6, 7, 8, 9, 0])
condition = np.array([True, False, True, True, False])
result2 = np.where(condition, a, b)
print(result2)
# np.where可用于高维数组而x if condition else y 不行
data = np.arange(9).reshape(3, 3)
data2 = np.where(data < 5, 5, data)
print(data)
print(data2)
print('↑---------------------class9\n\n') # 数组统计,通过某些函数对整个数组或数组上的某个轴进行统计
# sum、mean、std、var、min、max、argmin(最小值对应的索引)、argmax、cumsum(所有元素累计和)、cumprod(所有元素累计积)
data = np.arange(9).reshape(3, -1)
mean = data.mean() # 对整个数组取平均值
print(mean)
mean2 = data.mean(1) # 第二个轴上取平均值,即每一列的平均值
print(mean2)
cumsum = data.cumsum()
print(cumsum) # 高维会自动转为1维
print('↑--------------------class10\n\n') # 布尔型数组操作
# 布尔型数组的元素为true和false,在运算过程中,true可视为1,false可视为0
data = np.array([True, False, True, True])
print(data.sum())
# .any()用于检查array中元素是否全为0,.all()用于检查array中元素是否全为1
# .any()——有一个TRUE则返回1,反之0;.all()——全为TRUE返回1,反之0
print(data.any())
print(data.all())
# .any()、.all()对非布尔型数组进行操作时,所有非零元素视为True
data = np.array([-1, 1])
print(data.all())
print('↑--------------------class11\n\n') # 数组排序
data = np.random.randn(6)
print(data)
# 两种写法等价
# data = np.sort(data) # 用np.sort()函数时不改变原数组,需要赋值操作
data.sort() # .sort()方法自动对元素组进行操作,无需重新赋值
print(data)
# 高维数组可对某一个轴进行排序
data = np.random.randn(3, 3)
print(data)
data.sort(1) # 对第二个轴(即每行)进行排序
print(data)
print('↑--------------------class12\n\n') # 集合运算
# 数组元素唯一化
data = [1, 2, 3, 3, 3]
data = np.unique(data) # np.unique(data) 不对原数据进行去重操作,需要赋值
print(data)
# intersect1d(x,y) 返回公共元素,即交集,有序; union1d(x,y)返回并集,有序; setxor1d(x,y)返回两个集合的异或集(元素级运算)
# setdiff1d(x,y) 类似集合之差,即在x中而不在y中的元素(非对称,注意这一点)
data1 = [1, 2, 3]
data2 = [1, 3, 5]
delta = np.setdiff1d(data1, data2)
print(delta)
# in1d(x,y) 对元素级对象,返回x中每个元素是否在y中
inornot = np.in1d(data1, data2)
print(inornot)
print('↑--------------------class13\n\n') # 数据的保存与读取
data = np.arange(1, 10).reshape(3, 3)
np.save('data.npy', data) # 以二进制格式保存数组data,文件格式.npy
data2 = np.load('data.npy') # 读取,上一行的逆过程
print(data2)
data = np.random.randn(3, 3)
np.savetxt('data.txt', data, delimiter=',') # 以txt格式保存data
data2 = np.loadtxt('data.txt', delimiter=',') # 读取txt文件到data2这个数组
print(data2)
print('↑--------------------class14\n\n') # 矩阵的线性代数运算
# numpy把常用的线性代数运算放在numpy.linalg库中
data1 = np.arange(1, 10).reshape(3, 3)
data2 = np.eye(3) + np.ones((3, 3))
print(data1)
print(data2)
print('')
multiply = np.dot(data1, data2)
print(multiply)
print('')
inv = np.linalg.inv(data2) # 逆矩阵
print(inv)
print(np.dot(data2, inv))
det = np.linalg.det(data1) # 行列式
print('')
print(det) # 非满秩矩阵
lamda, x = np.linalg.eig(data2) # 求特征值(lamda)与特征向量(x)
print(x)
print(lamda)
x = x.T # 转置 再取出每一行即为各个特征值对应的特征向量
print(np.dot(data2, x[0]))
print(lamda[0] * x[0]) # 这一行与上一行结果相同,验证了A·x = lamda·x
print('')
# linalg中还有迹、QR分解、SVD分解、解线性方程、最小二乘等函数
print('↑--------------------class15\n\n') # 随机模块,np.random
# random.seed(),随机种子,使随机特性可复现
# 要指出的是,一次seed可以是整个程序的随机性均可复现,但不同地方的随机生成值不同,每次生成随机数前给定seed,则每个随机数相同
np.random.seed(0)
for i in range(5):
print(np.random.random()) # .random()生成一个随机数
print('')
for i in range(5):
np.random.seed(0)
print(np.random.randn())
print(np.random.randn(3, 3)) # .randn()按照标准正态分布生成随机值,可指定shape
for i in range(5):
print(np.random.normal(loc=50, scale=10)) # 给定均值和方差的正态分布,loc均值,scale标准差
print(np.random.permutation(10)) # 生成给定长度的随机序列
# 还有其他分布的随机数生成函数,beta()生成服从beta分布的随机数;chisquare()-卡方分布;
# gamma()-gamma分布;uniform()-[0,1)区间内的均匀分布
print('↑--------------------class16\n\n') # end
print("----------That's all----------------- \n total time is %.5f s" % (time.time() - start))