Numpy

Python中Numpy库的学习

Posted by CHY on June 21, 2020

本节主要记录Python中Numpy库的学习过程,以生信修炼手册和官方文档为基础。

基本知识

numpy中的多维数组称之为ndarray, 是由一系列相同数据类型的对象构成的集合。在numpy中,最基本的构建矩阵的方法是通过array函数。

import numpy
a = numpy.assay([(1,2,3),(,4,5,6)])  # 创建矩阵
type(a)
a.ndim  # 维度信息
a.shape  # 每个维度的尺寸
a.size  # 数组中元素个数
a.dtype  # 数组中元素基本数据类型
# 方法
import numpy as np
np.arange(1,10,3) # 等差数列
np.linspace(0,8,3) # 指定个数,自动划分步长
a = np.arange(6).reshape(3,2)  # 重新定义矩阵维度
np.zeros((2, 4))  # 初始化矩阵并用0填充
np.ones((2, 4))  # 初始化矩阵并用1填充
np.empty((2, 3))  # 初始化矩阵并用随机数填充

numpy中切片方法与R语言中的矩阵数据框类似。

掩码数组

掩码的意思主要指对数组中特定内容进行掩盖,被掩盖的部分使用短横杠表示。掩码数组中只有未被掩藏的元素参与计算。

import numpy.ma as ma
import numpy as np
a = np.arange(5)
ma.masked_equal(a,2)  # 等于2的元素被掩盖
ma.masked_not_equal(a,2) # 不等于2的元素被掩盖
ma.masked_greater(a,2)  # 大于2的元素被掩盖
ma.masked_less(a,2)  # 小于2的元素被掩盖
ma.masked_greater_equal(a,2) # 大于等于2的元素被掩盖
ma.masked_less_equal(a,2) # 小于等于2的元素被掩盖
ma.masked_outside(a,1,3) # 小于1大于3的元素被掩盖
ma.masked_inside(a,1,3)  # 大于等于1,小于等于3的元素被掩盖

Numpy中的广播机制

针对不同形状的数字进行运算时,首先尝试采用广播机制,将数组调整为统一的形状再进行运算。将较小数组进行延伸,保持和较大数组同一形状。
具体操作流程:

  1. 第一步,判断输出结果的数组尺寸,即shape属性,取输入数组的每个轴的最大值
  2. 第二步,将shape属性与输出数组不一致的话输入数组进行广播,要求二者之间只可以有一个轴尺寸是不同的,而且必须是1
  3. 第三步,利用广播之后的数组进行对应项的算术运算,输出结果

常用的数学运算和统计函数汇总

总结数值型数组相关的数学运算和统计函数。
通函数-ufunc:一类对数组中的元素逐个操作的函数。

import numpy as np
# 构建两个数值数组
a = np.arange(4)
b = np.arange(1,5)
np.add(a,b)   # 对应位置数值相加
np.subtract(a,b) # 相减
np.multiply(a,b)  # 相乘
np.divide(a,b)  # 相除
np.power(a,b)  # 乘方
np.remainder(a,b)  # 取余数
np.mod(a,b)   # 取余数
np.fmod(a,b)  # 取余数
np.divmod(a,b)  # 取余数和商
np.absolute(a)  # 绝对值
np.fabs(a)  # 绝对值
np.rint(a)  np.around(a) np.round(a) # 四舍五入
np.fix(a)  np.trunc(a)  # 只保留整数位
np.floor(a)  # 向下取整
np.ceil(a)  # 向上取整
np.exp(a)  # 自然对数的指数
np.exp2(a)  # 2的指数
np.log(a)  # 自然对数为底的对数
np.log2(a) # 2为底的对数
np.log10(a)  # 10为底的对数
np.sqrt(a)  # 平方根
np.square(a)  # 平方
# 统计函数(根据单词意思判断用法)
np.amin(a)
np.amax(a)
np.nanmin(a) np.namax(a)
np.sum(a)
np.nansum(a)
np.ptp(a) # 极差
np.percentile(a, q = [25, 50, 75])  np.nanpercentile(a, q = [25, 50, 75])  np.quantile(a, q = [0.25, 0.5, 0.75])  np.nanquantile(a, q = [0.25, 0.5, 0.75])# 百分位数
np.mean(a) np.average(a) np.nanmean(a) 
np.median(a)  np.nanmedian(a)
np.std(a)  np.nanstd(a)
np.var(a)  np.nanvar(a)
np.histogram(a, bins = [0, 20, 40, 60, 80, 100]) # 计算区间内的频数

遍历技巧

当内置通函数不能满足分析要求时,可以考虑一些遍历技巧。

# 内置for循环
# 一维数组遍历元素;二维数组遍历每一行
for i in a:
    print(i);

# flat迭代器
# 返回数组的迭代器,一层for循环就能搞定多维数组
for i in a.flat:
    print(i)

# nditer迭代器
# 与flat类似,但可以指定遍历顺序,C表示C语言风格,优先处理行;F表示Fortran,优先处理列
for i in np.nditer(a,order = "C"):
    print(i)
for i in np.nditer(a,order = "F"):
    print(i)
# nditer中op_flags参数允许修改数组中的元素
for i in np.nditer(a, op_flags = ['readwrite']):
    i *= 2
for i in np.nditer(a, op_flags = ['writeonly']):
    i += 2
# nditer可以自动使用广播遍历。

数组操作相关函数

需要提前了解两个概念,副本是一个数组的完整拷贝,就是说,先对原始数据进行拷贝,生成一个新的数组,新的数组和原始数组是独立的,对副本的操作并不会影响到原始数组;视图是一个数组的引用,对引用进行操作,也就是对原始数据进行操作,所以修改视图会对应的修改原始数组。

# 明确副本还是视图
import numpy as np
a = np.arange(12)
a.reshape(3,4)  # 副本
a.resize(3,4)  # 视图
# 将多维数组转换为一维数组
a.ravel(order = "C")  
a.ravel(order = "F")  # C和F指定行列先后顺序
a.flatten(order = "C")  # 同上
a.flatten(order = "F") 
# 数组转置
a.T
a.transpose()
a.swapaxes(0,1)
np.rollaxis(a,1,0)
# 数组的连接
# 按行连接
np.concatenate((a,b.reshape(1,-1)),axis = 0)
np.append(a, b.reshape(1,-1), axis = 0)
np.vstack((a,b.reshape(1,-1)))
# 以列合并
np.concatenate((a,b.reshape(1,-1)),axis = 1)
np.append(a, b.reshape(1,-1), axis = 1)
np.hstack((a,b.reshape(-1,1)))
# 合并数组必须具有相同的维度
# 元素的增加和删除
np.insert(a,1,b,axis = 0)
np.insert(a,1,b,axis = 1)
np.delete(a,1,axis = 0)
np.delete(a,1,axis = 1)
# 集合操作
np.intersect1d(a,b)  # 取交集
np.setdiff1d(a,b)  # 取a中的差集
np.setdiff1d(b,a)  # 取b中的差集
np.setxor1d(a,b)  # a,b差集的合集
np.union1d(a,b)  # 合集
# 排序/去重
np.unique(a) # 取唯一值
np.unique(a,return_counts=True) # 获取每个元素出现的次数
np.sort(a)
a.sort()

随机数生成技巧

numpy.random是numpy的一个子模块,用于生成随机数,在新版的numpy中,有以下两种生成随机数的方式RandomState和Generator。新版推荐Generator。

import numpy as np
np.random.seed(5) # 设定随机数种子
np.random.rand() # RandomState
rng = np.random.default_rng(5)  # 设定随机数种子
rng.random()  # Generator
# 对于RandomState
np.random.rand(2)  # 一维数组
np.random.rand(2,2) # 二维数组
np.random.sample((2,2))
np.random.random((2,2))
np.random.randn(2,2)  # 抽取标准正态分布的值
np.random.randint(9, 14, size = (2, 2)) # 定义范围内的整数
# 对于Generator
rng = np.random.default_rng()
rng.random(2)
rng.random(2,2)
rng.integers(9, 14, size=(2, 2))
# 序列中随机抽取
np.random.choice(a,2)
rng.choice(a,2)
# 随机打乱序列
np.random.shuffle(a)
rng.shuffle(a)
# 随机抽取符合分布的序列
np.random.normal(size=(2,2))
rng.normal(size=(2,2))
# binomial 二项分布
# chisquare 卡方分布
# normal 正态分布
# poisson 泊松分布
# standard_normal 标准正态分布
# uniform 均匀分布

文件读写

读取内容生成矩阵

# loadtxt适合数据量较小的文件
# 文件中不能含有缺失值
np.loadtxt('a.txt')
np.loadtxt('a.txt',skiprows = 1)
np.loadtxt('a.txt', delimiter='\t')
np.loadtxt('a.txt', comments = '#')  # 注释行会被跳过
np.loadtxt('a.txt', usecols = (1, ))  # 选择对应的列
x, y = np.loadtxt('a.txt', unpack = True)  # 返回仍为矩阵

# genfromtxt适合数据量较大的文件
# 用法与loadtxt相似
np.genfromtxt()
np.genfromtxt('a.txt', missing_values = 'NA')
np.genfromtxt('a.txt', missing_values = 'NA', filling_values = 0) # 指定填充

# load加载npy/npz格式的二进制文件
np.load()

numpy参考手册1
numpy参考手册2